背景:该篇文章总结于在原生的工程中接入EasyAR的SurfaceTracking的过程中遇到的一些问题,有一些问题是知识性的问题,有一些问题是可以称之为是坑的问题。

关键词:

Android原生中有关OpenGL的渲染设置

EasyAR初始化失败

EasyAR照相机黑屏

在Android Studio中进行有关EasyAR矩阵的调试(矩阵数据变的很诡异)

如何在自己的引擎中进行设置EasyAR提供的Projection Matrix(投影矩阵)和View Matrix(观察矩阵)

点击人物无法命中,或者没有办法正确命中

低配机进入AR模式之后,拍摄的视频背景卡顿问题

1、Android原生中有关OpenGL的渲染设置

这一块内容其实和AR的东西不是很相关,但是一般来说,工程里面接入ARSDK的话。肯定是想绘制自己的虚拟人物,在移动平台上,OpenGL又是不可或缺的一个部分,所以这一部分应该是有一些可以借鉴的内容。

因为之前工程里面的ARSDK接入的是Vuforia的GroundPlane(以下简称Vuforia),所以按照Vuforia的官网提供的Android事例,自己工程中的结构完全按照其官网事例进行设置,包括里面的session控制Vuforia的生命周期以及子类View继承GLSurface来进行渲染的设置。

所以接入EasyAR-SurfaceTracking(以下简称EasyAR)的第一步,就是先去将Vuforia从原来的工程中移除掉。

这里吐槽一下自己的感想:Vuforia关于这里的结构的设计,真的很严密,有专门控制功能的类,有专门掌管Vuforia生命周期的类,有专门进行渲染设置的类,以及功能的逻辑,错误的判断等真的很值得借鉴。相比于EasyAR,就会更加的简易,也更容易我们去理解,对于我这种新手还是比较友好的。

当然也可以把EasyAR的结构设计成和Vuforia的一样,但是有点小题大做了,因为相比于EasyAR,Vuforia里面的概念还是比较多,设备跟踪、智能地形等等,但是程序还是应该越简单越好(大佬说的,照做就是了)。

所以在我的程序里面,关于这里的设置就只有一个MainActivity.java、GLView.java、以及EasyAR官网提供的例子的中的HelloAR.java和BackGroundRender.java(最后一个文件名字我记不清了,就是用来渲染拍摄的视频流背景的那个文件)。

Tip:官网的例子中还有一个BoxRender.java的文件,用来渲染一个立方体,这个其实在接入的过程中可以留着,可以先去将盒子画出来,然后再去一步步的接入自己的渲染部分。然后完全接入的时候,再去将这部分删除掉就可以了。

EasyAR里面关于SurfaceTracking总共就只有三个文件:HelloAR(管理AR的相关接口),BoxRender(渲染盒子),BGroundRender(背景的渲染)。

下面说一下关于这几个文件结构的设计:

MainActivity.java文件里面是主要的Activity,并且只有这么一个Activity,负责进行EasyAR的最外层的管理,因为在我的工程里面,还有一些通过JNI和C++交互的部分,所以我将EasyAR最外层的管理放在这个类里面。

和Activity匹配的页面布局(XML文件)我使用的很简单,就只是写了一个进入AR的按钮,和一个退出AR的按钮,在这个XML里面,将XML的上下文配置为MainActivity,MainActivity类继承的是:Application类,没什么主义的地方。

在MainActivity的成员变量里面,有一个GLView类型的成员变量:mView。

在OnCreate方法里面,使用setContentView函数将这个成员变量mView设置为当前Activity的View视图。

这里其实我刚开始的时候不是很明白通过xml设置和通过这个View来设置有什么区别,总结一下:可以在某一些层面上将这个xml和mView理解为同一个东西,都是用来设置界面的长相的,只不过如果我们在代码里面一直使用代码来添加按钮,拖动条,进度条之类的,会让我们的代码文件显的特别的臃肿,所以此时,我们将所有有关控件的设置,都抽离出来,组成一个xml文件,这个文件里面只用来设置UI控件的样式,然后我们在代码文件里面就只需要使用就可以了,或者在需要的时候做一些更改,这样子我们的代码结构就会变的很简单明了。

GLView.java文件

这个文件就是主要和OpenGl相关,这个GLView我们需要让其继承自GLSurfaceView类 ,有关GLSurfaceView这个类是Android对于SurfaceView类的更高的一层封装,目的就是为了让我们能在Android原生更方便的使用OpenGL。

继承了这个GLSurfaceView类之后,我们必需要做的就是重载里面的三个函数:

OnSurfaceCreate、OnSurfaceChanged、OnDrawFrame

这三个函数的实现必须放在setRenderer函数里面,这个函数传进去的参数是一个GLSurfaceView里面的Renderer类型的变量。

在这个变量里面,我们要重载里面的三个函数。

第一个函数:OnSurfaceCreate

作用:用来创建渲染OpenGL界面的函数,也就说第一次执行就会先执行这个函数

第二个函数:OnSurfaceChanged

作用:当手机横竖屏转的时候,就会调用这个函数进行宽高切换

第三个函数:OnDrawFrame

这个函数是我们的重点函数,因为这个函数会每一帧都会去调,然后就是作为我们的render驱动,我渲染我们的虚拟人物

setRenderer(new GLSurfaceView.Renderer() {@Overridepublic void onSurfaceCreated(GL10 gl, EGLConfig config) {}@Overridepublic void onSurfaceChanged(GL10 gl, int w, int h) {}@Overridepublic void onDrawFrame(GL10 gl) {}});

除了使用setRenderer函数重载这3个函数之外,我们还可以设置下面这些:

setEGLContextFactory(new ContextFactory());
setEGLConfigChooser( translucent ?new ConfigChooser(8, 8, 8, 8, depth, stencil) :new ConfigChooser(5, 6, 5, 0, depth, stencil) );setEGLWindowSurfaceFactory(new WindowSurfaceFactory());
setPreserveEGLContextOnPause(true);

这些就是设置OpenGL的上下文有关的东西,里面的参数可以使用默认的,也可以使用自己写的类,我这里是使用的自己写的类,下面可以将这些代码贴上来。应该可以直接在你们的工程里面去用,因为这里主要还是记录和EasyAR相关的东西,所以这里的GLSurfaceView就不多说了,网上其他博客还是有很多更详细的资料。

这一部分的最后:按照EasyAR官方例子上,我们可以在这个GLView的类里面声明一个HelloAR类型的变量,然后使用这个变量去调用HelloAR类里面的render函数,再将这个render函数放在刚才的onDrawFrame里面就可以启动我们的render循环。

在这一个部分,我遇到了一些问题:就是关于有关OpenGL的包,

import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.egl.EGLSurface;
import javax.microedition.khronos.opengles.GL10;

我只有使用这些包的时候,才不会报错,之前使用下面这些包的时候,会有一些奇怪的符号不能识别的问题,查了一下,说是两个包差别不大,上面的算是升级版,但是具体升级什么了,我没有太细搞,有知道的大佬可以分享一下。

import android.opengl.GLES30;
import android.opengl.GLSurfaceView;

2、EasyAR初始化失败

初始化EasyAR的引擎需要去官网申请一个开发者账号,然后在里面申请一个免费版的Key,自己工程里面用的是哪一个版本的,就申请那个版本的key,Key只能向下兼容,不能向上兼容,然后将自己app的ID填进去

ID在自己的工程的Grandle里面,之后就会给你一个字符串,这个字符串,我们在就可以用来初始化EasyAR的引擎,如果key和ID没有对应上的话,就会在log里面提示

Log.e("HelloAR", "Initialization Failed.");

可以在控制台搜索相关字符,看看有没有这个提示,来判断引擎有没有初始化成功。

这个初始化,完全可以将例子中的初始化搬过来,我是放在MainActivity的onCreate里面直接初始化的。这一部分只要注意一下,应该没什么大问题。

3、EasyAR照相机黑屏

进入AR模式之后的黑屏就比较好搞了,因为上一步我们已经确定了引擎的初始化成功,现在出现黑屏的问题很有可能就是我们的app摄影机的权限没有申请成功,我们可以打开app的详情信息来看一下 ,里面有没有摄影机的权限。

有了这个权限之后,拍摄应该正常了。

4、在Android Studio中进行有关EasyAR矩阵的调试(矩阵数据变的很诡异)

因为我是的工程是使用Android Studio进行开发的。所以在Engine初始化完成,摄影机正常打开之后,此时我们就应该进行自己的虚拟人物的绘制,如果只是绘制他的一个小盒子,就没什么意思了。

这个时候我建议大家,先正确的绘制出来他自己的盒子,然后再去将程序改成绘制自己的虚拟人物,一步一步来。

而绘制虚拟人物的话,我们就需要从EasyAR中获取两个矩阵:Projection 矩阵和 View 矩阵。

然后在设置矩阵的开发过程中,我们一定会去调试程序,这个时候就会有有一个十分严重的问题,通过调试,我们在观察器里面监视我们的矩阵里面的数字。

而这个监视的过程无论是附加断点还是直接Debug启动,中间AS(Android Studio)都会为我们做一步动作:将我们的.so文件一起打包进app,然后还有其他的一些有关build的操作。这些操作在稍微大一点的工程里面是需要一些时间的,这个时间根据自己工程的大小而决定,我这个工程,附加一次断点,中间的这些操作耗时大概在20s左右。

A:当你进入了AR模式,然后打了断点,这个时候进行附加断点调试操作。中间经历了大概20s左右的空白,此时AR拍摄的画面会卡顿,前一帧和后一帧的画面就会不连贯,而我们的EasyAR的平面特征点计算的依据就是前一帧和后一帧画面一起的计算结果,所以中间附加断点的20s,就会让EasyAR的计算结果不准确,这个时候你观测你的矩阵数据,就会发现:矩阵的数据十分诡异,变得十分的大,正常来说,EasyAR里面的单位是:米。应该数据最大在10左右,就可以了,再大的话,你就应该注意一下是不是出了问题。

B:当我们使用Debug启动App调试的时候,进入AR之前我们已经将断点打好了,这个时候我们第一次命中断点的时候,就会发现,这个矩阵里面的数据全是0。是因为EasyAR在刚开始的几帧画面里面,正在计算这个画面的特征点,此时还没有计算出来对应的Projection Matrix和 View Matrix。所以多跑几帧就可以了。我的大概跑5帧左右(也就是断点命中5次左右)就会发现矩阵有数据了。然后这个时候,你继续调试,就会发现数据有可能也变的越来越大。这和上面的原因是一样的,因为打断点的时候,我们要观察监视器里面的数据,然后再去跑程序,中间就有会有很长时间的停顿,这也会影响EasyAR的引擎判断。

所以我建议的方法就是:打log咯,这个时候,EasyAR计算的是连续帧,所以数据比较准确,就不会出现上面的问题了。

这个两个问题搞了我好久。最后发现只能将锅甩给我自己。没有完全的理解EasyAR,冒然调试,锅从天降。

5、如何在自己的引擎中进行设置EasyAR提供的Projection Matrix(投影矩阵)和View Matrix(观察矩阵)

6、点击人物无法命中,或者没有办法正确命中

这两个问题可以放在一起总结,因为都是关于矩阵的设置,但是这两个问题是我在不同的时间遇到的,所以就抽出来成两个问题。

因为AR的效果呈现主要靠的是View Matrix ,这是刚开始想法,所以开始的时候我就只去设置EasyAR提供的ViewMatrix,效果正确之后,我就没有去管EasyAR提供的ProjectionMatrix,而是让自己的渲染引擎计算ProjectionMatrix去给人物用。这个时候,就会出现第六个问题。

所以ProjectionMatrix一定是要设置的。

然后关于ViewMatrix,按照文档的说法,EasyAR提供的矩阵是行主序,和OpenGL的列主序是不一样的,所以首先我们使用到自己的OpenGL引擎中的时候,就需要行列转置,剩余的呢,就按照正常的处理就可以,

因为我自己的渲染引擎里面虽然使用的是OpenGL,但是矩阵的方式都是按照DX的方式来的,也就是出了行列不一样之外,还有左右手也不一样,所以我在我的矩阵的时候时候,要经过行列转置和左右手坐标系互换两步。

关于ViewMatrix,我是通过解析里面的观察点坐标和观察方向的向量,然后通过这两个数据计算出一个新的投影矩阵。

然后还要设置一个upDir向量,这个向量决定的是你怎么去观察,是脑袋立起来观察(0,1,0),还是脑袋朝右,然后观察(1,0,0),其他的话就可以根据自己的渲染引擎进行推算,我现在将我的设置方法放出来。希望对你设置自己的渲染引擎的矩阵有所帮助。

    void SetMat(const float* pfProjMat, const float* pfViewMat){// 传进来的两个参数就是EasyAR的Projection Matrix和View MatrixKVec3 vLookAt;KVec3 vEyePos;KVec3 vUp;KMATRIX viewMatrix;KMATRIX proMatrix;KMATRIX pfProjMatrix;// 进行View Matrix的设置memcpy(&viewMatrix, pfViewMat, sizeof(viewMatrix));MatrixTranspose(viewMatrix,viewMatrix);// 行列转置// 因为我自己渲染引擎的矩阵,使用的是DX的矩阵,所以需要转成DX的矩阵_MatrixDXToOpengl(viewMatrix,viewMatrix);// 转成DX的矩阵// 从View Matrix里面解析出来Eye Positon和 LookAt的数据DecomposeMarixLookAtLH(viewMatrix,vEyePos,vLookAt);SetPosition(vEyePos * 100);SetLookAt(vLookAt * 100);SetUpDir(KVec3(1,0,0));// Projection Matrix的设置memcpy(&pfProjMatrix, pfProjMat, sizeof(pfProjMatrix));MatrixTranspose(pfProjMatrix,pfProjMatrix);_MatrixDXToOpengl(pfProjMatrix,pfProjMatrix);float fNear = 10.0f;float fFar = 40000.0f;float a = (fFar) / (fFar - fNear);float b = -fFar * fNear / (fFar - fNear);proMatrix.f[0] = pfProjMatrix.f[0];proMatrix.f[1] = pfProjMatrix.f[1];proMatrix.f[4] = pfProjMatrix.f[4];proMatrix.f[5] = pfProjMatrix.f[5];proMatrix.f[10] = a;proMatrix.f[11] = 1;proMatrix.f[14] = b;SetARMode();SetProjMat(proMatrix.f);}

上面的设置里面还用到了转置函数和OpenGL矩阵转DX矩阵的函数,以及解析Eye Posotion、LookAt的函数,

因为这些函数都是使用我自己封装的矩阵类型,所以就不上传了,网上也可以找得到,不想写的话,就从网上找一个,也不难。

Tip:传进来的ViewMatrix参数是经过求逆的,这个求逆的函数是EasyAR里面自带的:

传进来的时候使用这个函数对View Matrix进行求逆一下:

像这样(官网例子里面的)

7、低配机进入AR模式之后,拍摄的视频背景卡顿问题

这个我问题,刚开始我以为是adb的问题,但是后来发现低配机器上这个问题一直存在,所以就差了一下文档,如下图:

文档就说InputFrame的数量太少,导致渲染卡住,然后InputFrame的默认数量是8,这个时候我们就可以扩大这个数量,我是直接扩大到32.为什么扩大到32我不是很清楚但是问题是解决了。

目前我不是很清楚,什么样的大小算是一个合适的大小,因为我在高配机上使用的默认的大小就正常。这个文档里也没有说过。

然后我们点开上面的蓝色的文字:CameraDevice,然后我们就进入了CameraDevice类里面,发现了这么一段话:

就会更加的印证我的想法是正确的,接着我们在下面找一找接口咯。会发现,有这么一个接口,有点意思:

然后使用CameraDevide类的对象(HelloAR初始化的那个部分的时候,就可以找得到)调用这个接口,将InputFrame的数量搞大一些。具体数值可以看你咯,我设置的32;文档也没有说怎么设置合适。

放在最后的吐槽:

关于EasyAR的文档,确实让我有点琢磨不同,因为之前有使用过Vuforia,所以Vuforia的文档之详细,简直真的有点强了,每一个接口都会有对应的小例子。除了都是英文,真的没啥好吐槽的,可是EasyAR的文档,关于接口的说明就只是每一种语言列出来,然后统一一个解释,有时候万一有那个接口没有理解,压根没有什么其他的资料可以让你查找。

关于AR,大家使用的Vuforia会更多一些,因为毕竟是高通爸爸搞的,有钱有人有力。但是关于Vuforia的GroundPlane功能支持的国产的手机,一个牌子竟然不超过5部,清楚的记得某米手机,只有最新的几台才支持,但是三星的几乎是全系列都支持了,很难搞。但是Vuforia的效果确实的很不错,还支持多人物,多锚点。但是还是抵不住EasyAR支持几乎全部的Android机的诱惑。毕竟产品还是得让大部分人都能使用的上。

EasyAR的技术人员也说了,他们没有向其他的大公司的技术方向靠,所以平面识别这里,他们自己也承认做的一般。但是我觉得够用,毕竟也没有水印,基础版本全免费。Vuforia的基础班还有个大大的水印。但是EasyAR给人的感觉像是疯狂的向Unity靠拢。但是究其原因,毕竟Unity也是另一个爸爸,能在Unity用,可以让更多的游戏开发者使用这个EasyAR。

总结:

关于(Android / iOS)原生本地接EasyAR的开发者,有点难搞哦。

细数Android原生工程接入EasyAR-SurfaceTracking遇到的坑相关推荐

  1. 原生工程接入Flutter实现混编

    前言 上半年我定的OKR目标是帮助团队将App切入Flutter,实现统一技术栈,变革成多端融合开发模式.Flutter目前是跨平台方案中最有潜力实现我们这个目标的,不管是Hybird还是React ...

  2. uniapp android原生,在uni-app项目中集成Android原生工程

    [TOC] # 在uni-app项目中集成Android原生工程 按照官方的方案,我们如果进行本地打包的话,需要重新创建一个Android原生工程,于是就会导致我们管理多个项目,切来切去的也麻烦. 经 ...

  3. android p preview_细数 Android P 开发者预览版中最不能错过的新特性

    原标题:细数 Android P 开发者预览版中最不能错过的新特性 2018年安卓巴士全球开发者论坛-重庆站 [线下活动]春天到了 跟小编一起去重庆嗨皮吧~ Android P 应用适配新特性1.Pr ...

  4. 云原生是什么?细数云原生的5大特征

    云原生是什么?细数云原生的5大特征 00 云原生是什么? 01 轻.快.不变的基础设施 02 弹性服务编排 03 开发运营一体化 04 微服务架构 05 无服务模型 小结 来源:大数据DT 导读:随着 ...

  5. 基于Mui与H5+开发webapp的Android原生工程打包步骤(使用新版本5+SDK与Android studio)(部分内容转自dcloud官网)...

    文章背景: dcloud官网给出的打包步骤对于有一定安卓打包基础的同学来说比较容易掌握,但是对于webapp小白来讲有的地方可能没有说的太具体.下面我给大家介绍的详细一点,保证大家按照步骤就能学会打包 ...

  6. Mac android原生工程中潜入react-native混合开发项目搭建

    最近公司有意向要用react-native做开发,自己在去年的时候也接触过,不过没有深入探讨,这两天,抽出时间看了看,顺便看了一下文档,做了一个简易的dome,由于我本人用的mac os 系统,Mac ...

  7. zbar android解码错误,Android原生编解码接口 MediaCodec 之——踩坑

    关键帧 MediaCodec 有两种方式触发输出关键帧,一是由配置时设置的 KEY_FRAME_RATE和KEY_I_FRAME_INTERVAL参数自动触发,二是运行过程当中经过 setParame ...

  8. 细数Android 7.0“牛轧糖”的五大缺陷:不支持悬浮窗口

    导语:当前,Android 7.0 Nougat(牛轧糖)已经开始被缓慢部署至全球各地的Android设备中.按照惯例,仍然是Nexus设备首先获得谷歌最新的移动操作系统,其他的智能手机则还需要等待一 ...

  9. DCloud之Android原生工程配置

    目录 一.开发环境准备 1.安装 Android Studio 2.下载 App离线SDK 二.导入工程 三.配置工程 1.基础库配置 2.build.gradle 中添加资源引用 3.应用配置 (1 ...

  10. 细数Android开发者的艰辛历程,已拿offer附真题解析

    笼统来说,中年程序员容易被淘汰的原因其实不外乎三点. 1.输出能力已到顶点.这个人奋斗十来年了,依旧碌碌无为,很明显这人的天花板就这样了,说白了,天赋就这样. 2.适应能力越来越差.年纪大,有家庭,老 ...

最新文章

  1. html 左右选择框,jquery实现下拉框左右选择功能
  2. bootstrap34-带有导航栏的字体图标
  3. 使用WCF传输DataTable:DataTable和Xml格式的字符串相互转换(C#)
  4. maven之setting.xml的配置详解
  5. 王琦:5G新视频应用的机会窗口将在2-3年内
  6. leetcode 222. 完全二叉树的节点个数(dfs)
  7. 腾讯云开发者大会 | 腾讯云大学首次与业界顶尖厂商合作的线上学习专区重磅发布...
  8. 【动态规划】P1057 传球游戏
  9. 关于调试,很大的感触,请看下面的c程序
  10. udp聊天?使用udp+python实现多人聊天室
  11. 新建samba配置步骤
  12. 我毕业一年后。生活的艰辛。我的程序人生该怎么走
  13. Visio安装网盘,我不会破解
  14. Springboot毕设项目高校食堂饭卡管理824ct(java+VUE+Mybatis+Maven+Mysql)
  15. 黑马程序员机器学习Day1学习笔记
  16. otsu阈值分割算法原理_OpenCV学习30--阈值分割的OTSU算法
  17. git中rejected的解决方法
  18. rtx2060为什么叫智商卡_老电脑升级RTX2060,——性能,功耗,静音都一步到位!...
  19. Ant Design 实现表格合并
  20. 在痛苦的日子里笑出声来

热门文章

  1. 几何公差:GPS 2019 产品几何技术规范 (GDT)
  2. 2022软考软件设计师复习(上午题)
  3. linux内核手写板驱动,【Linux系统编程应用】 Linux Input子系统(一)
  4. MTK6589反向修改拼包法操作流程
  5. Cisco思科交换机Vlan划分
  6. 孤儿进程与僵尸进程产生及其处理
  7. 腾讯业务架构:六大事业群
  8. WINCE Activesync 同步问题
  9. 计算机硬件兼容性,教你如何查看电脑硬件的兼容性
  10. 湖北工业大学机械c语言考试试题,关于部分同学重新参加《C语言程序设计》、《计算机及网络应用基础》课程补考的通知...