接着上一篇说,集成完成之后,你打开项目中Jni目录,你会看到这几个文件
重点是helloar.cc 这个文件,我们看它的代码
void HelloAR::render() { glClearColor(0.f, 0.f, 0.f, 1.f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); Frame frame = augmenter_.newFrame(); if(view_size[0] > 0){ AR::resizeGL(view_size[0], view_size[1]); if(camera_ && camera_.isOpened()) view_size[0] = -1; } augmenter_.setViewPort(viewport_); augmenter_.drawVideoBackground(); glViewport(viewport_[0], viewport_[1], viewport_[2], viewport_[3]); for (int i = 0; i < frame.targets().size(); ++i) { AugmentedTarget::Status status = frame.targets()[i].status(); if (status == AugmentedTarget::kTargetStatusTracked) { //这里就是说明,已经识别到了,开始绘制方块的地方 Matrix44F projectionMatrix = getProjectionGL(camera_.cameraCalibration(), 0.2f, 500.f); Matrix44F cameraview = getPoseGL(frame.targets()[i].pose()); ImageTarget target = frame.targets()[i].target().cast_dynamic<ImageTarget>(); renderer.render(projectionMatrix, cameraview, target.size()); } } }helloar.cc中的这个方法就是相当于识别图片的一个方法,那么我们如何在识别成功后,做自己的事情呢?我们需要将其绘制方块的代码去掉,然后在改一些地方(注意,传统JNI调用Java方法,如 env->findClass…. env->getStaticMethodId() 之类的在这里不能使用),我们需要按照接下来的步骤来做。
更改MainActivity中的nativeRender()方法,让其返回值是String public static native String nativeRender();2.更改helloar.cc文件,Jni方法返回值,需要改为jstring
JNIEXPORT jstring JNICALL JNIFUNCTION_NATIVE(nativeRender(JNIEnv* env, jobject obj)); 在下面找到Jni的具体实现方法,改为 JNIEXPORT jstring JNICALL JNIFUNCTION_NATIVE(nativeRender(JNIEnv* env, jobject)) { return env->NewStringUTF(ar.render()); }3.更改helloar.cc文件中的HelloAr类中的render()方法,将其返回值改为 const char*
class HelloAR : public AR { public: HelloAR(); virtual void initGL(); virtual void resizeGL(int width, int height); virtual const char* render(); private: Vec2I view_size; Renderer renderer; }; 往下拉,改实现方法 const char* HelloAR::render() { glClearColor(0.f, 0.f, 0.f, 1.f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); Frame frame = augmenter_.newFrame(); if(view_size[0] > 0){ AR::resizeGL(view_size[0], view_size[1]); if(camera_ && camera_.isOpened()) view_size[0] = -1; } augmenter_.setViewPort(viewport_); augmenter_.drawVideoBackground(); glViewport(viewport_[0], viewport_[1], viewport_[2], viewport_[3]); const char *p="n"; for (int i = 0; i < frame.targets().size(); ++i) { AugmentedTarget::Status status = frame.targets()[i].status(); if (status == AugmentedTarget::kTargetStatusTracked) { const char* c_s= frame.targets()[i].target().name(); return c_s ; }else { return p; } } return p; }这里只有一点说明,rame.targets()[i].target().name() 方法,得到的是你json文件配置的name值,如: 当然你也可以rame.targets()[i].target().uid(); 得到uid属性(前提是你json文件配置了这个属性)。然后我return了回去,它会回调Renderer类中的onDrawFrame方法。
4.更改ar.cc文件,ctrl+f找到 render 方法,将其返回值改成 const char*
5.更改ar.hpp文件,ctrl+f找到render方法,将其返回值改成const char*
6.更改 renderer.cc 和 renderer.hpp 文件,同上
7.最后一步更改Renderer类
public class Renderer implements GLSurfaceView.Renderer { public void onSurfaceCreated(GL10 gl, EGLConfig config) { ArScannerFragment.nativeInitGL(); } public void onSurfaceChanged(GL10 gl, int w, int h) { ArScannerFragment.nativeResizeGL(w, h); } //更改这个方法 public void onDrawFrame(GL10 gl) { String bo = null; try { bo = new String(ArScannerFragment.nativeRender().getBytes(),"UTF-8"); if(!"n".equals(bo)) { //是否正在暂用 if(!isEnable) { isEnable = true; EasyAR.onPause(); mCallBack.scannerFished(bo); }else { //否则不打开 } } } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } } onDrawFrame 这个方法,你可以简单理解为 识别成功后的回调方法,你可以在这里去写你的逻辑,比如,展示些你的模型。之前在MainActivity中,我已经将nativeRender的返回值改为我String,所以这里我要用String去接收其返回值。1. 识别成功后,我想展示一个自己的模型? 说明: 我并不推荐你根据官方的方法去替换模型文件,我们只需要这个EasyAr提供扫描结果,然后将结果传给我们,之后由我们自己处理,比如我想展示一个模型,加载一个网页,一个View之类的。
如何做? 1. 如果你想展示模型,你需要下载jpct-ae库,它是安卓平台下的游戏引擎库,我们用它加载3d模型,我们下载它,然后解压,将其的lib引入到你的项目中。
之后进入其代码目录下,找到HelloWord.java文件,复制到你的项目中,之后怎么调用它,就是在你识别成功后,直接调用这个类就行了。我用了Jpct-ae,但是背景如何透明啊?
// 类似java.awt.*中的Color类 private RGBColor back = new RGBColor(0, 0, 0); //这里指定alpha值为0 private View bottom; private float touchTurn = 0.0f; private float touchTurnUp = 0.0f; // private float touchDown = 0; // // private float baseValue = 0; // private float baseCameraValue = 100; // private float scale = 0; private float xpos = -1; private float ypos = -1; private Object3D cube = null;// 3d模型对象 // 每秒帧数 private int fps = 0; // 光照类 private Light sun = null; private Light moon = null; private ProgressDialog progressDialog; protected void onCreate(Bundle savedInstanceState) { progressDialog = new ProgressDialog(this); progressDialog.setMessage("加载中,请稍候..."); progressDialog.show(); // Logger类中 jPCT中一个普通的用于打印和存储消息,错误和警告的日志类。 // 每一个JPCT生成的消息将被加入到这个类的队列中 Logger.log("onCreate"); // 如果本类对象不为NULL,将从Object中所有属性装入该类 if (master != null) { copy(master); } super.onCreate(savedInstanceState); mGLView = new GLSurfaceView(getApplication()); // 使用自己实现的 EGLConfigChooser,该实现必须在setRenderer(renderer)之前 // 如果没有setEGLConfigChooser方法被调用,则默认情况下,视图将选择一个与当前android.view.Surface兼容至少16位深度缓冲深度EGLConfig。 //然后这里 mGLView.setZOrderOnTop(true); mGLView.setEGLConfigChooser(8, 8, 8, 8, 16, 0); mGLView.getHolder().setFormat(PixelFormat.TRANSLUCENT);这样,你就完成了展示自己的模型了(模型的更改,在这个类中,通过R.raw指定,你可以替换为自己的模型)。
下一篇我们说,如何动态的加载识别图片,而不是固定。
