RxJava与ARCore:增强现实开发新思路
关键词:RxJava、ARCore、增强现实开发、响应式编程、新思路
摘要:本文将深入探讨RxJava与ARCore在增强现实开发中的结合应用。首先介绍了相关的背景知识,包括目的、预期读者等。接着详细解释了RxJava和ARCore的核心概念,用通俗易懂的语言类比生活现象进行讲解,并阐述了它们之间的关系。之后给出了核心算法原理、数学模型等内容,还通过项目实战展示了代码实现和详细解读。最后探讨了实际应用场景、工具资源推荐、未来发展趋势与挑战等,帮助开发者开拓增强现实开发的新思路。
背景介绍
目的和范围
在当今科技飞速发展的时代,增强现实(AR)技术已经逐渐走进人们的生活,为人们带来了全新的交互体验。然而,AR开发过程中往往会面临一些复杂的问题,比如异步操作的管理、数据的流式处理等。本文的目的就是探讨如何利用RxJava这一强大的响应式编程库与ARCore这个谷歌推出的增强现实开发平台相结合,为增强现实开发提供新的思路和方法。范围主要涵盖了RxJava和ARCore的基本概念、它们的结合原理、实际项目中的应用以及未来的发展趋势等方面。
预期读者
本文预期的读者主要是对增强现实开发感兴趣的开发者,包括初学者和有一定经验的开发者。对于初学者来说,可以通过本文了解RxJava和ARCore的基本概念和使用方法,为进一步学习增强现实开发打下基础;对于有一定经验的开发者来说,可以从中获取新的开发思路和技巧,提升自己的开发水平。
文档结构概述
本文将首先介绍RxJava和ARCore的核心概念,用生动形象的方式解释它们的原理和用途。然后阐述这两个核心概念之间的关系,展示它们如何协同工作。接着会详细讲解核心算法原理和具体操作步骤,给出相关的数学模型和公式,并通过项目实战展示代码的实际应用和详细解释。之后会探讨实际应用场景、推荐相关的工具和资源,最后分析未来的发展趋势与挑战,并进行总结和提出思考题。
术语表
核心术语定义
- RxJava:是一个在Java虚拟机上使用可观测的序列来组成异步的、基于事件的程序的库,它采用了响应式编程的思想。
- ARCore:是谷歌推出的一个增强现实开发平台,它可以让开发者在安卓设备上创建出令人惊叹的增强现实应用。
- 增强现实(AR):是一种将虚拟信息与真实世界巧妙融合的技术,通过电脑技术将虚拟的信息应用到真实世界,真实的环境和虚拟的物体实时地叠加到了同一个画面或空间同时存在。
相关概念解释
- 响应式编程:可以理解为一种关注数据流和变化传播的编程范式。就好像我们在玩多米诺骨牌,当一个骨牌倒下时,会引发一系列的连锁反应,后面的骨牌会依次倒下。在响应式编程中,数据的变化就像倒下的骨牌,会自动触发一系列的操作。
- 异步操作:在编程中,有些操作可能会花费很长时间,比如网络请求、文件读写等。如果采用同步的方式,程序会一直等待这些操作完成,导致界面卡顿。而异步操作则可以让程序在等待这些操作完成的同时继续执行其他任务,就像我们在烧水的时候可以同时去做其他事情,等水烧开了再回来处理。
缩略词列表
- AR:增强现实(Augmented Reality)
- Rx:响应式扩展(Reactive Extensions)
核心概念与联系
故事引入
想象一下,你是一个魔法世界的小魔法师,你有两个神奇的法宝。一个法宝就像一个聪明的小管家,它可以帮你管理各种任务,当有新的任务到来时,它会按照一定的顺序和规则来安排这些任务,而且还能处理任务之间的复杂关系,这个法宝就是RxJava。另一个法宝就像一个神奇的画笔,它可以在现实世界的画布上画出各种奇幻的景象,让现实世界和奇幻世界融合在一起,这个法宝就是ARCore。现在,你要利用这两个法宝,在现实世界中创造出令人惊叹的魔法场景,这就是我们要探讨的RxJava与ARCore在增强现实开发中的结合。
核心概念解释(像给小学生讲故事一样)
> ** 核心概念一:RxJava**
> 我们可以把RxJava想象成一个超级快递员。在我们的生活中,当我们有很多包裹要寄出去的时候,我们可以把这些包裹交给快递员,快递员会按照一定的路线和顺序把包裹送到不同的地方。而且,快递员还会处理一些突发情况,比如某个包裹需要加急送达,或者某个地址发生了变化。在编程中,RxJava就像这个快递员,它可以管理各种数据和事件,把它们按照一定的规则进行处理和传递。例如,当我们从网络上获取数据时,可能会有很多数据源源不断地传来,RxJava可以对这些数据进行过滤、转换等操作,就像快递员对包裹进行分类和整理一样。
> ** 核心概念二:ARCore**
> 把ARCore想象成一个神奇的画家。画家可以在一张空白的画布上画出各种各样的美丽图案。而ARCore可以在现实世界这个“画布”上添加虚拟的物体和场景。比如,你拿着手机,打开一个使用ARCore开发的应用,你就可以看到手机屏幕上的现实世界中出现了一只可爱的小精灵在跳舞。ARCore通过手机的摄像头和传感器,感知现实世界的环境,然后把虚拟的物体准确地叠加到现实世界中,就像画家在画布上准确地画出图案一样。
> ** 核心概念三:增强现实(AR)**
> 增强现实就像是一场奇妙的魔法表演。在表演中,魔术师会把一些神奇的东西和现实场景结合起来。比如,魔术师可能会让一只虚拟的鸽子从现实的桌子上飞起来。增强现实就是利用技术手段,把虚拟的信息和真实的世界融合在一起,让我们在现实世界中看到一些原本不存在的东西,给我们带来全新的视觉体验。
核心概念之间的关系(用小学生能理解的比喻)
> 解释核心概念之间的关系,例如:RxJava、ARCore和增强现实就像一个魔法团队,ARCore是魔法师,负责在现实世界中施展魔法,画出虚拟的场景;RxJava是魔法助手,负责管理魔法所需的各种能量和信息;增强现实就是这个魔法团队最终呈现给观众的精彩表演。
> ** 概念一和概念二的关系:**
> 就像魔法师和魔法助手的关系。在增强现实开发中,ARCore负责创建和展示虚拟场景,而RxJava可以帮助ARCore管理和处理与虚拟场景相关的数据和事件。比如,当我们通过ARCore在现实世界中添加一个虚拟的模型时,可能需要从网络上获取这个模型的数据。RxJava可以帮助我们异步地获取这些数据,并且对数据进行处理,确保数据准确无误地传递给ARCore,让ARCore能够正确地展示虚拟模型。这就好比魔法助手为魔法师准备好施展魔法所需的材料,并且把材料整理好交给魔法师。
> ** 概念二和概念三的关系:**
> ARCore是实现增强现实的重要工具。就像画家是画出美丽画作的关键人物一样,ARCore通过其强大的功能,能够将虚拟物体准确地叠加到现实世界中,从而实现增强现实的效果。没有ARCore,我们很难在现实世界中如此方便地看到虚拟的物体和场景,也就无法体验到增强现实带来的奇妙感觉。
> ** 概念一和概念三的关系:**
> RxJava为增强现实开发提供了更好的数据管理和事件处理能力。在增强现实应用中,会有很多数据和事件需要处理,比如用户的交互事件、传感器的数据等。RxJava可以帮助我们高效地处理这些数据和事件,让增强现实应用更加流畅和稳定。就像魔法助手可以帮助魔法师更好地控制魔法的能量和效果,让魔法表演更加精彩一样,RxJava可以让增强现实应用的体验更加出色。
核心概念原理和架构的文本示意图(专业定义)
- RxJava原理:RxJava基于观察者模式和迭代器模式,通过Observable(被观察者)发射数据,Observer(观察者)接收数据。Observable可以对数据进行各种操作,如map、filter等,然后将处理后的数据发送给Observer。整个过程是异步的,数据可以以流的形式进行处理。
- ARCore原理:ARCore主要通过三个关键技术来实现增强现实效果,分别是运动跟踪、环境理解和光照估计。运动跟踪通过手机的摄像头和传感器,实时跟踪手机的位置和姿态;环境理解可以识别现实世界中的平面和特征点;光照估计可以让虚拟物体的光照效果与现实环境相匹配。
- 结合架构:在增强现实开发中,RxJava可以与ARCore结合使用。ARCore负责创建和管理虚拟场景,而RxJava可以用于处理与虚拟场景相关的数据和事件。例如,通过RxJava异步获取网络数据,然后将数据传递给ARCore进行虚拟物体的渲染。
Mermaid 流程图
核心算法原理 & 具体操作步骤
核心算法原理
在RxJava与ARCore结合的增强现实开发中,涉及到一些核心算法原理。
RxJava相关算法
- 过滤算法:在RxJava中,我们可以使用filter操作符对数据进行过滤。例如,当我们从网络上获取一系列数据时,可能只需要其中符合某些条件的数据。就像我们从一堆水果中挑选出苹果一样,filter操作符可以帮助我们筛选出我们需要的数据。
import io.reactivex.Observable;
public class FilterExample {
public static void main(String[] args) {
Observable<Integer> numbers = Observable.just(1, 2, 3, 4, 5);
numbers.filter(num -> num % 2 == 0)
.subscribe(System.out::println);
}
}
在这个例子中,我们创建了一个包含1到5的Observable,然后使用filter操作符筛选出其中的偶数,并将结果打印出来。
- 映射算法:map操作符可以对Observable发射的数据进行转换。就像我们把一种语言翻译成另一种语言一样,map操作符可以把一个数据类型转换为另一个数据类型。
import io.reactivex.Observable;
public class MapExample {
public static void main(String[] args) {
Observable<Integer> numbers = Observable.just(1, 2, 3);
numbers.map(num -> num * 2)
.subscribe(System.out::println);
}
}
在这个例子中,我们将Observable中的每个数字都乘以2,然后输出结果。
ARCore相关算法
- 运动跟踪算法:ARCore使用视觉惯性里程计(VIO)算法来跟踪手机的位置和姿态。VIO算法结合了手机摄像头的视觉信息和惯性传感器(如加速度计和陀螺仪)的数据,通过对图像特征点的匹配和运动估计,来确定手机在现实世界中的位置和方向。
- 平面检测算法:ARCore通过分析摄像头捕捉到的图像,使用机器学习算法来检测现实世界中的平面。它会识别出平面的边界和方向,以便在这些平面上放置虚拟物体。
具体操作步骤
集成RxJava和ARCore到项目中
- 首先,在项目的build.gradle文件中添加RxJava和ARCore的依赖。
dependencies {
implementation 'io.reactivex.rxjava3:rxjava:3.1.5'
implementation 'com.google.ar:core:1.29.0'
}
- 配置ARCore的权限。在AndroidManifest.xml文件中添加以下权限:
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera.ar" />
使用RxJava处理ARCore相关数据
- 假设我们要从网络上获取一个虚拟模型的数据,并使用ARCore进行渲染。首先,我们可以使用RxJava进行异步网络请求。
import io.reactivex.rxjava3.schedulers.Schedulers;
import io.reactivex.rxjava3.core.Observable;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import java.io.IOException;
public class NetworkRequest {
public static Observable<String> getModelData(String url) {
return Observable.create(emitter -> {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.build();
try {
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
emitter.onNext(response.body().string());
emitter.onComplete();
} else {
emitter.onError(new IOException("Network request failed"));
}
} catch (IOException e) {
emitter.onError(e);
}
}).subscribeOn(Schedulers.io());
}
}
- 在ARCore的Activity中,我们可以订阅这个Observable,获取数据并进行渲染。
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.disposables.Disposable;
public class ARActivity extends AppCompatActivity {
private Disposable disposable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ar);
String modelUrl = "https://example.com/model.gltf";
disposable = NetworkRequest.getModelData(modelUrl)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(data -> {
// 在这里使用ARCore进行模型渲染
// 示例代码省略
}, error -> {
// 处理错误
error.printStackTrace();
});
}
@Override
protected void onDestroy() {
super.onDestroy();
if (disposable != null && !disposable.isDisposed()) {
disposable.dispose();
}
}
}
数学模型和公式 & 详细讲解 & 举例说明
运动跟踪的数学模型
在ARCore的运动跟踪中,使用了刚体运动的数学模型。刚体在三维空间中的运动可以用旋转和平移来描述。
旋转表示
旋转可以用四元数(Quaternion)来表示。四元数是一种扩展的复数,它可以更方便地表示三维空间中的旋转。一个四元数
q
q
q 可以表示为:
q
=
w
+
x
i
+
y
j
+
z
k
q = w + xi + yj + zk
q=w+xi+yj+zk
其中,
w
w
w 是实部,
x
x
x、
y
y
y、
z
z
z 是虚部,并且满足
i
2
=
j
2
=
k
2
=
i
j
k
=
−
1
i^2 = j^2 = k^2 = ijk = -1
i2=j2=k2=ijk=−1。
四元数的乘法可以用来组合两个旋转。假设
q
1
q_1
q1 和
q
2
q_2
q2 是两个四元数,它们的乘法定义为:
q
1
q
2
=
(
w
1
w
2
−
x
1
x
2
−
y
1
y
2
−
z
1
z
2
)
+
(
w
1
x
2
+
x
1
w
2
+
y
1
z
2
−
z
1
y
2
)
i
+
(
w
1
y
2
−
x
1
z
2
+
y
1
w
2
+
z
1
x
2
)
j
+
(
w
1
z
2
+
x
1
y
2
−
y
1
x
2
+
z
1
w
2
)
k
q_1q_2 = (w_1w_2 - x_1x_2 - y_1y_2 - z_1z_2) + (w_1x_2 + x_1w_2 + y_1z_2 - z_1y_2)i + (w_1y_2 - x_1z_2 + y_1w_2 + z_1x_2)j + (w_1z_2 + x_1y_2 - y_1x_2 + z_1w_2)k
q1q2=(w1w2−x1x2−y1y2−z1z2)+(w1x2+x1w2+y1z2−z1y2)i+(w1y2−x1z2+y1w2+z1x2)j+(w1z2+x1y2−y1x2+z1w2)k
平移表示
平移可以用三维向量 t = [ t x , t y , t z ] T \mathbf{t} = [t_x, t_y, t_z]^T t=[tx,ty,tz]T 来表示。
刚体运动表示
刚体在三维空间中的运动可以用一个变换矩阵
T
\mathbf{T}
T 来表示,它是一个
4
×
4
4\times4
4×4 的矩阵:
T
=
[
R
t
0
1
]
\mathbf{T} = \begin{bmatrix} R & \mathbf{t} \\ 0 & 1 \end{bmatrix}
T=[R0t1]
其中,
R
R
R 是一个
3
×
3
3\times3
3×3 的旋转矩阵,它可以由四元数转换得到。
举例说明
假设我们有一个初始的刚体位置和姿态,用变换矩阵 T 1 \mathbf{T}_1 T1 表示,经过一段时间的运动后,刚体的旋转可以用四元数 q q q 表示,平移可以用向量 t \mathbf{t} t 表示。那么新的刚体位置和姿态可以通过以下步骤计算:
- 将四元数 q q q 转换为旋转矩阵 R R R。
- 构建新的变换矩阵
T
2
\mathbf{T}_2
T2:
T 2 = [ R t 0 1 ] \mathbf{T}_2 = \begin{bmatrix} R & \mathbf{t} \\ 0 & 1 \end{bmatrix} T2=[R0t1] - 计算最终的变换矩阵 T f i n a l = T 2 T 1 \mathbf{T}_{final} = \mathbf{T}_2\mathbf{T}_1 Tfinal=T2T1。
通过这个最终的变换矩阵,我们可以得到刚体在新的位置和姿态下的坐标。
项目实战:代码实际案例和详细解释说明
开发环境搭建
- 安装Android Studio:Android Studio是开发安卓应用的官方集成开发环境(IDE),可以从官方网站下载并安装。
- 配置Java开发环境:确保已经安装了Java Development Kit(JDK),并且配置好了环境变量。
- 创建新的Android项目:打开Android Studio,选择“Start a new Android Studio project”,按照向导创建一个新的项目。
源代码详细实现和代码解读
布局文件(activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.ar.sceneform.ArSceneView
android:id="@+id/arSceneView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
这个布局文件中,我们使用了ARCore的ArSceneView来显示增强现实场景。
主Activity(MainActivity.java)
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import com.google.ar.core.Config;
import com.google.ar.core.Session;
import com.google.ar.sceneform.ArSceneView;
import com.google.ar.sceneform.ux.ArFragment;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.schedulers.Schedulers;
public class MainActivity extends AppCompatActivity {
private ArFragment arFragment;
private ArSceneView arSceneView;
private Disposable disposable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
arFragment = (ArFragment) getSupportFragmentManager().findFragmentById(R.id.arFragment);
arSceneView = arFragment.getArSceneView();
// 初始化ARCore会话
Session session = null;
try {
session = new Session(this);
Config config = new Config(session);
session.configure(config);
arSceneView.setupSession(session);
} catch (Exception e) {
e.printStackTrace();
}
// 使用RxJava异步加载虚拟模型
disposable = loadModel()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(model -> {
// 将模型添加到场景中
// 示例代码省略
}, error -> {
// 处理错误
error.printStackTrace();
});
}
private io.reactivex.rxjava3.core.Observable<Model> loadModel() {
return io.reactivex.rxjava3.core.Observable.create(emitter -> {
// 模拟加载模型的过程
try {
Thread.sleep(2000);
Model model = new Model();
emitter.onNext(model);
emitter.onComplete();
} catch (InterruptedException e) {
emitter.onError(e);
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
if (disposable != null && !disposable.isDisposed()) {
disposable.dispose();
}
}
}
代码解读:
- 在
onCreate
方法中,我们首先获取了ArFragment
和ArSceneView
,然后初始化了ARCore的会话。 loadModel
方法使用RxJava的Observable
来模拟异步加载虚拟模型的过程。- 通过
subscribeOn
和observeOn
方法,我们指定了异步操作的线程和结果回调的线程。 - 在
onDestroy
方法中,我们确保在Activity销毁时取消订阅,避免内存泄漏。
代码解读与分析
- 异步操作管理:使用RxJava可以方便地管理异步操作,避免了传统的回调地狱问题。在这个项目中,我们使用
Observable
来异步加载虚拟模型,使得代码更加简洁和易于维护。 - 线程管理:通过
subscribeOn
和observeOn
方法,我们可以灵活地控制异步操作的线程和结果回调的线程。在Android开发中,UI操作必须在主线程中进行,因此我们使用observeOn(AndroidSchedulers.mainThread())
确保模型加载完成后在主线程中进行渲染。 - 错误处理:RxJava提供了强大的错误处理机制。在
subscribe
方法中,我们可以传入一个错误处理的回调函数,当加载模型过程中出现错误时,会调用这个回调函数进行错误处理。
实际应用场景
教育领域
在教育领域,RxJava与ARCore的结合可以创造出更加生动有趣的学习体验。例如,在学习历史时,可以通过ARCore在现实场景中展示古代建筑和文物的虚拟模型,让学生更加直观地了解历史文化。同时,使用RxJava可以管理与这些虚拟模型相关的数据,如模型的介绍、历史背景等,实现数据的流式处理和异步加载。
游戏领域
在游戏开发中,增强现实游戏可以给玩家带来沉浸式的体验。例如,开发一款寻宝游戏,玩家可以在现实世界中寻找虚拟的宝藏。ARCore可以在现实场景中准确地放置宝藏的虚拟模型,而RxJava可以处理玩家的交互事件,如点击宝藏、获取宝藏信息等,让游戏更加流畅和有趣。
商业展示领域
在商业展示中,商家可以使用ARCore创建虚拟的商品展示场景,让顾客在现实环境中更加直观地了解商品的特点和功能。RxJava可以用于管理商品信息的获取和更新,确保顾客能够及时获取最新的商品信息。
工具和资源推荐
开发工具
- Android Studio:官方的安卓开发IDE,提供了丰富的开发工具和调试功能。
- Sceneform SDK:谷歌提供的用于创建AR应用的SDK,它简化了在ARCore上创建3D场景的过程。
学习资源
- RxJava官方文档:详细介绍了RxJava的使用方法和原理。
- ARCore官方文档:提供了ARCore的开发指南和示例代码。
- GitHub上的开源项目:可以搜索一些使用RxJava和ARCore开发的开源项目,学习他人的代码和经验。
未来发展趋势与挑战
发展趋势
- 更加智能化:未来,RxJava与ARCore的结合可能会引入更多的人工智能技术,如机器学习、计算机视觉等。例如,通过机器学习算法对用户的行为进行分析,提供更加个性化的增强现实体验。
- 跨平台应用:随着技术的发展,可能会出现更多支持跨平台的增强现实开发框架,使得开发者可以在不同的操作系统上使用RxJava和ARCore进行开发。
- 与其他技术的融合:AR技术可能会与虚拟现实(VR)、物联网(IoT)等技术进行深度融合,创造出更加复杂和强大的应用场景。
挑战
- 性能优化:增强现实应用通常需要处理大量的图像和数据,对设备的性能要求较高。如何使用RxJava和ARCore优化应用的性能,减少卡顿和延迟,是一个重要的挑战。
- 数据安全和隐私:在增强现实应用中,会涉及到用户的个人信息和现实环境的数据。如何保障这些数据的安全和隐私,是开发者需要面对的问题。
- 用户体验设计:如何设计出更加自然和舒适的增强现实交互方式,提高用户的体验感,也是一个需要不断探索的领域。
总结:学到了什么?
> ** 核心概念回顾:**
> 我们学习了RxJava、ARCore和增强现实的核心概念。RxJava就像一个超级快递员,负责管理和处理数据和事件;ARCore就像一个神奇的画家,能够在现实世界中画出虚拟的场景;增强现实则是将虚拟信息与真实世界融合的技术。
> ** 概念关系回顾:**
> 我们了解了RxJava、ARCore和增强现实之间的关系。RxJava可以帮助ARCore管理和处理与虚拟场景相关的数据和事件,ARCore是实现增强现实的重要工具,而RxJava为增强现实开发提供了更好的数据管理和事件处理能力。
思考题:动动小脑筋
> ** 思考题一:** 你能想到生活中还有哪些地方可以应用RxJava与ARCore结合的技术吗?
> ** 思考题二:** 如果你是一个开发者,你会如何进一步优化RxJava与ARCore结合的增强现实应用的性能?
附录:常见问题与解答
问题一:RxJava和传统的异步编程有什么区别?
答:传统的异步编程通常使用回调函数来处理异步操作,当异步操作嵌套较多时,会导致代码变得复杂,出现回调地狱的问题。而RxJava采用响应式编程的思想,通过Observable和Observer的方式来处理异步操作,代码更加简洁和易于维护,并且提供了丰富的操作符来处理数据。
问题二:ARCore支持哪些设备?
答:ARCore支持大多数运行Android 7.0(Nougat)及以上版本的设备。具体的设备支持情况可以参考ARCore的官方文档。
扩展阅读 & 参考资料
- 《RxJava实战》
- 《ARCore开发指南》
- RxJava官方文档:https://github.com/ReactiveX/RxJava
- ARCore官方文档:https://developers.google.com/ar
- GitHub上的相关开源项目:https://github.com/search?q=rxjava+arcore