谷歌在8月28日发布了arcore,下面就是对 arcore的 一次初步的探索,主要是根据google的英文文档实践了一次,把相关的东西做了一下整理和记录。也方便不喜欢阅读英文文档的朋友们参考:),下面就直接上内容了->
使用Androidstudio 开发ARcore 步骤:
1、安装了as 2.3以上,并且有7.0(api 24)以上的sdk平台。
2、最好使用google pixel 类型的手机。
3、下载ARCore的sdk。
4、 在开始ARcore开发之前呢,最好对android 开发和OpenGl有一些基础的理解,需要具备的两个条件:1.能够创建android app,2,能够用OpenGL ES来在android 平台上展示图形。 对于第一个能力基本都具备,但是第二个能力的话,还是需要有一些准备的。因此会重点介绍如何使用OpenGLES来展示图形。
4.1Displaying Graphics withOpenGL ES
Android 的framework层提供了大量的标准工具来创建具有吸引人眼球的那些功能性的ui。但是如果你想更深入的控制绘制或者来探索3维图形的现实,那么就需要一些其他工具,比如OpenGLES,它能够使用GPU加速,因此能够显示更高质量的动画等。在Android 上使用OpenGLES主要分为以下几个步骤:
1) 搭建OpenGLES的环境
Learn how to set up an Android application to be able to drawOpenGL graphics.
要想使用OpenGleS画图,需要创建一个容器,一个直接的办法就是实现 GLSurfaceView
和 GLSurfaceView.Renderer
。
GLSurfaceView
是一个容器,用来放
OpenGl
绘制的图形,
GLSurfaceView.Render
是用来控制在其中绘制的内容。
GLSurfaceView
是一种把
OpenGLES
融进你应用的方法。对于全屏或者是接近全屏的图像
view
,这是一个合理的选择。如果在应用中只有局部的视图需要使用
OpenGlES
绘制,那么可以考虑使用
TextureView
。而且,如果愿意多写一些代码的话,使用
SurfaceView
也可以构建一个
OpenGL ES
的
view
。
接下来就来构建一个实现了
GLSurfaceView
和
GLSurfaceView.Render
的最简单的应用,使用一个简单的
Activity
完成。
1. 在Manifest中声明对OpenGl ES的使用
为了能够在应用中使用OpenGL ES2.0,需要在清单文件中加入下面内容:
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
如果使用了texture compression(纹理压缩),那么必须声明使用了哪种压缩格式,以便只在合适的设备上安装。
<supports-gl-texture android:name="GL_OES_compressed_ETC1_RGB8_texture" />
<supports-gl-texture android:name="GL_OES_compressed_paletted_texture" />
2.创建Activity并setContentView为自己创建的GLSurfaceView对象。
public class OpenGLES20Activity extends Activity {
private GLSurfaceView mGLView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Create a GLSurfaceView instance and set it
// as the ContentView for this Activity.
mGLView = new MyGLSurfaceView(this);
setContentView(mGLView);
}
}
注意:OPenGleS2.0需要2.2以上的api支持。
3.创建 GlSurfaceView Object
GLSurfaceView是一个能够在上面画Opengles图像的特殊的view,它上面没有做太多绘制工作,实际的控制是在GLSurfaceView.Render中,需要在GLSurfaceView中设置一个GLSurfaceView.Render的对象。一般来说,需要集成GLSurfaceview,以便在里面获取触摸事件。
class MyGLSurfaceView extends GLSurfaceView {
private final MyGLRenderer mRenderer;
public MyGLSurfaceView(Context context){
super(context);
// Create an OpenGL ES 2.0 context
setEGLContextClientVersion(2);
mRenderer = new MyGLRenderer();
// Set the Renderer for drawing on the GLSurfaceView
setRenderer(mRenderer);
}
}
可以在GLSurfaceView中设置renderMode来控制重回的时间,比如当数据发生改变的时候才去绘制。调用下面的方法来设置:
// Render the view only when there is a change in the drawing data
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
这个设置保证了只有当你调用requestRender()方法的时候,才回去重回GLSurfaceView,这样就保证了应用的效率。
4.创建一个Render类
这个Render类是控制与他关联的GLSurfaceView的绘制内容的类,有三个方回调方法会在绘制内容的时候被系统调用。分别是:
onSurfaceCreated(),
onDrawFrame(),在重新绘制View的时候调用
onSurfaceChanged().在View的几何形状改变时调用,比如屏幕的朝向改变的时候。
public class MyGLRenderer implements GLSurfaceView.Renderer {
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
// Set the background frame color
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}
public void onDrawFrame(GL10 unused) {
// Redraw background color
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
}
public void onSurfaceChanged(GL10 unused, int width, int height) {
GLES20.glViewport(0, 0, width, height);
}
}
这样就是用了OpenGLEs来绘制了一个简单的背景。
2) 定义形状(defining shape)
能够在OpenGL ES的 Context中定义形状 (shape)是创建高端图形杰作的第一步。下面介绍一些OpenGl es和 android设备屏幕相关的协同系统,以及如何定义一些基本的形状等。
1. 定义三角形
OPenGLES允许使用三维空间坐标来描绘物体,所以在画三角形之前,必须要指定其坐标。在OpenGL中,典型的做法是 定义一个float类型的顶点数组。为了高效,你可以把这些坐标写到一个 ByteBuffer中,然后把它传到OpenGLES 的 graphics的pipeline中 来处理。
public class Triangle {
private FloatBuffer vertexBuffer;
// number of coordinates per vertex in this array
static final int COORDS_PER_VERTEX = 3;
static float triangleCoords[] = { // in counterclockwise order:
0.0f, 0.622008459f, 0.0f, // top
-0.5f, -0.311004243f, 0.0f, // bottom left
0.5f, -0.311004243f, 0.0f // bottom right
};
// Set color with red, green, blue and alpha (opacity) values
float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f };
public Triangle() {
// initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(
// (number of coordinate values * 4 bytes per float)
triangleCoords.length * 4);
// use the device hardware's native byte order
bb.order(ByteOrder.nativeOrder());
// create a floating point buffer from the ByteBuffer
vertexBuffer = bb.asFloatBuffer();
// add the coordinates to the FloatBuffer
vertexBuffer.put(triangleCoords);
// set the buffer to read the first coordinate
vertexBuffer.position(0);
}
}
默认情况下,Openngles假设了一个坐标系统,[0,0,0](xyz)是GLsurfaceViewframe 的中心,[1,1,0]是右顶角,[-1,-1,0]是左底角,注意在OpenGles中定义坐标时,使用逆时针的方向来定义shape的顶点,因为绘制的顺序决定了哪边是图形的正面。而对与back face ,可以通过openGLES的面剔除(cull face)功能来选择不去绘制backface。原文原因:(If you try to use the face culling feature without knowing which sidesof your shapes are the front and back, your OpenGL graphics are going to look abit thin, or possibly not show up at all.)
2. 定义矩形
在OpenGL中定义三角形是比较简单的,但是如果定义一个复杂一点的形状比如 矩形时,典型的做法是使用两个三角形拼成一个矩形。
同样,需要按照逆时针的方式去定义图形的顶点,并且把这些顶点的值放到ByteBuffer中。为了避免坐标重复,需要使用一个绘制清单来告诉OpenGLES 图形管道 如何去绘制这些顶点。下面是绘制矩形的代码:
public class Square {
private FloatBuffer vertexBuffer;
private ShortBuffer drawListBuffer;
// number of coordinates per vertex in this array
static final int COORDS_PER_VERTEX = 3;
static float squareCoords[] = {
-0.5f, 0.5f, 0.0f, // top left
-0.5f, -0.5f, 0.0f, // bottom left
0.5f, -0.5f, 0.0f, // bottom right
0.5f, 0.5f, 0.0f }; // top right
private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices
public Square() {
// initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(
// (# of coordinate values * 4 bytes per float)
squareCoords.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(squareCoords);
vertexBuffer.position(0);
// initialize byte buffer for the draw list
ByteBuffer dlb = ByteBuffer.allocateDirect(
// (# of coordinate values * 2 bytes per short)
drawOrder.length * 2);
dlb.order(ByteOrder.nativeOrder());
drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(drawOrder);
drawListBuffer.position(0);
}
}
通常来讲,需要使用一些三角形的集合来绘制更为复杂的物体。
3) 绘制形状(shape)
在定义完了shape之后,就是去绘制它。使用openGLes2.0去绘制shape,需要在图形渲染管道(pipeline)中调用api来完成。
1. 初始化图形
在绘制之前,你必须初始化并加载你打算绘制的shape。除非图形的结构在你程序执行的过程中会发生改变。你需要在onSurfaceCreate()回调方法中来初始化shape,这样可以提高内存和执行的效率。
public class MyGLRenderer implements GLSurfaceView.Renderer {
...
private Triangle mTriangle;
private Square mSquare;
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
...
// initialize a triangle
mTriangle = new Triangle();
// initialize a square
mSquare = new Square();
}
...
}
2. 绘制图形(shape)
使用OpenGL2.0来绘制一个定义好的图形,需要大量的代码。因为你必须提供很多图像的细节给图形渲染管道。包括以下几点:
· Vertex Shader –画顶点的代码。.
· Fragment Shader –给图形的面 绘制颜色或者纹理的。.
· Program –一个OpenGLES对象,包含了绘制图形的着色器。
你需要至少一个 vertex shader 来绘制顶点和一个Fragment shader来绘制颜色。这些shaders必须被添加到一个 OpenGLES Program对象上,然后用这个program对象来绘制shape。下面是例子:
public class Triangle {
private final String vertexShaderCode =
"attribute vec4 vPosition;" +
"void main() {" +
" gl_Position = vPosition;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
...
}
包含OpenGL Shading Language(GLSL) 代码的shaders必须要先被编译然后才能用在OpenGL ES环境中。为了编译这些代码,在Renderer中创建一个工具方法:
public static int loadShader(int type, String shaderCode){
// create a vertex shader type (GLES20.GL_VERTEX_SHADER)
// or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
int shader = GLES20.glCreateShader(type);
// add the source code to the shader and compile it
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
在绘制图形之前,必须要把这些shader的代码进行编译,然后添加到OpenGLES program对喜爱南瓜中,并且进行连接到program对象。这些工作需要在被绘制物体的构造函数中进行,以保证只进行一次。
注意: 编译OpenGLES shader 并且连接到Program对象的cpu消耗是比较昂贵的,所以避免多次操作。如果在运行时还不知道要绘制的shader的内容,那么你应该先创建然后缓存起来以便后面使用。
public class Triangle() {
...
private final int mProgram;
public Triangle() {
...
int vertexShader = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER,
vertexShaderCode);
int fragmentShader = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER,
fragmentShaderCode);
// create empty OpenGL ES Program
mProgram = GLES20.glCreateProgram();
// add the vertex shader to program
GLES20.glAttachShader(mProgram, vertexShader);
// add the fragment shader to program
GLES20.glAttachShader(mProgram, fragmentShader);
// creates OpenGL ES program executables
GLES20.glLinkProgram(mProgram);
}
}
到这里,已经可以调用方法来绘制图形了。 绘制前需要你生命几个参数 告诉 渲染管道 你想绘制什么和如何绘制他们。由于绘制选项会根据图形的变化而变化,所以在你的图形类中,包含他们自己的绘制逻辑是个不错的方案。
在图形类中创建draw()方法,来设置position 和color分别到图形的vertextshader 和 fragment shader,然后执行绘制功能:
private int mPositionHandle;
private int mColorHandle;
private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
public void draw() {
// Add program to OpenGL ES environment
GLES20.glUseProgram(mProgram);
// get handle to vertex shader's vPosition member
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
// Enable a handle to the triangle vertices
GLES20.glEnableVertexAttribArray(mPositionHandle);
// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer);
// get handle to fragment shader's vColor member
mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
// Set color for drawing the triangle
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
// Draw the triangle
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
在图形类(Triangle.class)中写好了draw()方法后,需要在绘制物体的方法onDrawFrame()方法中调用 triangle对象的draw()方法:
public void onDrawFrame(GL10 unused) {
...
mTriangle.draw();
}
运行app,能够看到
但是这里还有一些问题,第一,光画个三角形,不酷;第二,三角形有点被挤压了,而且当屏幕朝向改变时,三角形的形状也会发生改变。这是因为被绘制物体的顶点没有根据GLSurfaceView展示的区域显示的部分来进行纠正。
4) 应用 设计(投影)和摄像机视图(apply projection and camera views)
在OpenGLES环境中,应用投影和摄像机视图 可以让你绘制的物体所见即所得。这种模拟实际的视角是通过对绘制物体的坐标进行数学转换来实现的,来看两个概念:
Projection- 这个转换根据GLSurfaceView的宽和高来调整绘制物体的坐标。如果没有这个计算的话,绘制的物体会因为视图窗口的比例不均等而受到挤压变形。投射转换只需要在OpenGL View创建或者改变的时候进行计算,改变时系统会调用onSurfaceChanged()方法。
Camera View- 摄像机视角,这个转换可以调整绘制物体的坐标到实际的摄像机视角。值得一提的是:在OpenGLES中,并没有真正的Camera 对象,但提供一个替代的工具方法,这个方法通过转化绘制物体的显示方式来模拟摄像机。摄像机视角的转换发生在你创建GLSurfaceView,或者是根据用户的动作来动态改变的时候。下面来看如何创建projection和 camera view,并应用到绘制图形的GLSurfaceView中。
1. 定义一个Projection
投影转换的数据在GLSurfaceView.Render类中的onSurfaceChange()方法中进行计算。下面的示例代码获取了GLSurfaceView的宽和高,然后调用Matix.frustumM()方法来发布了一个投射转换的矩阵:
// mMVPMatrix is an abbreviation for "Model View Projection Matrix"
private final float[] mMVPMatrix = new float[16];
private final float[] mProjectionMatrix = new float[16];
private final float[] mViewMatrix = new float[16];
@Override
public void onSurfaceChanged(GL10 unused, int width, int height) {
GLES20.glViewport(0, 0, width, height);
float ratio = (float) width / height;
// this projection matrix is applied to object coordinates
// in the onDrawFrame() method
Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}
这段代码填充了一个投射矩阵mprojectionMatix,你可以在onDrawFrame()方法中把它和camera view 的转换矩阵合并。
注意:仅仅把映射转换应用到你绘制的objects上会导致显示空的内容。通常,你必须同时应用 camera View转换,这样才能将物体显示到屏幕上。
2.定义一个Camera View(摄像机视角)
在转换绘制物体时,需要通过在Renderer类中添加一个camera view转换作为绘制进程的一部分。下面代码中,camera view转换通过调用 Matrix.setLookAtM()方法来实现,然后再将结果和之前计算出的投射矩阵相结合。最后将结合好的矩阵传递给绘制的图形。
@Override
public void onDrawFrame(GL10 unused) {
...
// Set the camera position (View matrix)
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
// Calculate the projection and view transformation
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
// Draw shape
mTriangle.draw(mMVPMatrix);
}
3.应用投影(projection)和摄像机视角转换(Camera Transformations)
为了能够在预览区域使用投射矩阵和摄像机视角矩阵的结果矩阵,首先要在之前定义Triangle类的 vertex shader中添加一个 matrix variable :
public class Triangle {
private final String vertexShaderCode =
// This matrix member variable provides a hook to manipulate
// the coordinates of the objects that use this vertex shader
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"void main() {" +
// the matrix must be included as a modifier of gl_Position
// Note that the uMVPMatrix factor *must be first* in order
// for the matrix multiplication product to be correct.
" gl_Position = uMVPMatrix * vPosition;" +
"}";
// Use to access and set the view transformation
private int mMVPMatrixHandle;
...
}
接下来,修改你的图像物体类的draw()方法,来接受合并后的转换矩阵,并且应用到图形的绘制中:
public void draw(float[] mvpMatrix) { // pass in the calculated transformation matrix
...
// get handle to shape's transformation matrix
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
// Pass the projection and view transformation to the shader
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
// Draw the triangle
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
一旦你正确地计算并且应用了projection 和 camera view转换,那么你的图形绘制出来之后就是按照正确的比例的,如下图:
现在你可以按照正确的比例去显示图形了。接下来给图形添加动作。
5) 添加动作
在屏幕上画图形是一个Opengl比较基础的一个功能,还可以用其他的图形框架中的类,比如通过使用Canvas 和 Drawable对象。OpenGL ES提供了附加的功能,比如在三维空间中移动和转换绘制物体,这样可以创建非常不错的用户交互体验。
1. 旋转一个图形
在你的Renderer中,创建另一个转换矩阵(一个旋转矩阵),然后把它合并到你的projection 和 camera view的转换矩阵中:
rivate float[] mRotationMatrix = new float[16];
public void onDrawFrame(GL10 gl) {
float[] scratch = new float[16];
...
// Create a rotation transformation for the triangle
long time = SystemClock.uptimeMillis() % 4000L;
float angle = 0.090f * ((int) time);
Matrix.setRotateM(mRotationMatrix, 0, angle, 0, 0, -1.0f);
// Combine the rotation matrix with the projection and camera view
// Note that the mMVPMatrix factor *must be first* in order
// for the matrix multiplication product to be correct.
Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0);
// Draw triangle
mTriangle.draw(scratch);
}
如果你的三角形在做了上述修改之后没有旋转,那么请确定去掉了 GLSurfaceView.RENDERMODE_WHEN_DIRTY
设置。
2. 开启持续渲染
去掉脏区更新的设置,如果设置了
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
那么OpenGL 会在旋转图形的时候只绘制一次,然后等待GLSurfaceView中调用requestRender()来进行重新绘制。
3. public MyGLSurfaceView(Context context) {
...
// Render the view only when there is a change in the drawing data.
// To allow the triangle to rotate automatically, this line is commented out:
//setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
}
注意:除非你想要绘制的图形在没有和用户交互的情况下自己变化,否则推荐将这个设置打开。以便有更好的cpu性能。在需要和用户做交互的时候,需要打开这个设置参数。
6) 响应用户的触摸事件
能够是OpenGL ES应用可以响应用户触摸事件的关键是在GLSurfaceViewzhong重新onTouchEvents()方法,来监听用户的触摸事件。
1. 创建一个Touch Listener
为了能够使你的OpenGLES应用响应用户的触摸事件,你必须在GLSurfaceView类中实现onTouchEvent()方法。下面的示例展示了如何去监听 MotionEvent.ACTION_MOVE事件,并且把它们转化成shape的旋转角度:
private final float TOUCH_SCALE_FACTOR = 180.0f / 320;
private float mPreviousX;
private float mPreviousY;
@Override
public boolean onTouchEvent(MotionEvent e) {
// MotionEvent reports input details from the touch screen
// and other input controls. In this case, you are only
// interested in events where the touch position changed.
float x = e.getX();
float y = e.getY();
switch (e.getAction()) {
case MotionEvent.ACTION_MOVE:
float dx = x - mPreviousX;
float dy = y - mPreviousY;
// reverse direction of rotation above the mid-line
if (y > getHeight() / 2) {
dx = dx * -1 ;
}
// reverse direction of rotation to left of the mid-line
if (x < getWidth() / 2) {
dy = dy * -1 ;
}
mRenderer.setAngle(
mRenderer.getAngle() +
((dx + dy) * TOUCH_SCALE_FACTOR));
requestRender();
}
mPreviousX = x;
mPreviousY = y;
return true;
}
注意,在计算了旋转的角度之后,上面的方法中调用了requestRender()方法来告诉渲染线程该渲染新的一帧了。这种调用方式是最有效率的,因为frame只有在角度发生改变的时候才需要绘制。当然,requestRender()方法有效的前提是,你设置了
GLSurfaceView.RENDERMODE_WHEN_DIRTY。所以需要在Renderer中调用setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY).
public MyGLSurfaceView(Context context) {
...
// Render the view only when there is a change in the drawing data
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
}
2. 暴露旋转的角度
上述的示例代码要求你能够算出旋转的角度,并在你的Renderer中,通过一个public的变量来记录它.由于renderer的代码在一个与主UI线程分离的线程中执行,所以必须将这个变量声明为volatile的.下面是相关声明变量的代码:
public class MyGLRenderer implements GLSurfaceView.Renderer {
...
public volatile float mAngle;
public float getAngle() {
return mAngle;
}
public void setAngle(float angle) {
mAngle = angle;
}
}
3. 让图形旋转
为了能够根据用户的touch input来产生旋转,去掉自动产生旋转角度的代码:
public void onDrawFrame(GL10 gl) {
...
float[] scratch = new float[16];
// Create a rotation for the triangle
// long time = SystemClock.uptimeMillis() % 4000L;
// float angle = 0.090f * ((int) time);
Matrix.setRotateM(mRotationMatrix, 0, mAngle, 0, 0, -1.0f);
// Combine the rotation matrix with the projection and camera view
// Note that the mMVPMatrix factor *must be first* in order
// for the matrix multiplication product to be correct.
Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0);
// Draw triangle
mTriangle.draw(scratch);
}
注意: setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
需要放在setRender(mRender)之后 ,否则有空指针。
5、 打开示例工程
6、 准备设备
注意arcore不支持虚拟设备,比如模拟器,需要使用物理设备,打开开发者模式,开启debug功能,下载ARCore Service,是一个arcore-preview.apk,使用adb进行安装:$adb install –r –d arcore-preview.apk。
7、 运行示例工程
下一步:需要 导入ARCore ARR library , 添加依赖,参考arcore的api可以 进行编程了,api:https://developers.google.com/ar/reference/java/com/google/ar/core/package-summary。 主要参考的是示例代码的注释。
注意 : arr也是一个as到处的压缩包,可以改后缀名为zip后进行解压缩。里面其实是一个moudel的目录结构。