(Android)Vuforia Native版本與jpct-ae結合
AR/VR技術交流群 129340649
Qualcomm的Vuforia引擎是最強大的增強現實引擎之一。將它和JPCT-AE結合是一個很好的想法,它可以讓你的Android裝置實現讓人驚奇的AR場景。
其中在Android端和iOS端的Vuforia Native版本是需要進行NDK程式設計,並且對於3D渲染這塊做的不是很好,它採用的方案是將模型檔案轉換成.h或者java檔案,將其中的點線面等資料儲存,然後使用OpenGL讀取並繪製。這種方案的弊端有很多,比如模型檔案過大,不適合多貼圖,渲染效果不好等等。將Vuforia與3D渲染引擎在原生程式碼中融合一直是我想做的事情,這篇稿子主要講述Android端的Vuforia原生程式碼與jpct-AE得融合。
jpct-AE是一款免費的Android 系統下的3D渲染引擎。他是一款基於OpenGL技術開發的3D圖形引擎(PC環境為標準OpenGL,Android為OpenGL ES), 以Java語言為基礎的,擁有功能強大的Java 3D解決方案。
Vuforia和jpct都是使用OpenGL es中的GLSurfaceView進行繪製顯示 的。開啟ImageTargetsRenderer.java檔案,這個是OpenGL渲染類,我們需要把Jpct的程式碼插入進來。
首先,為ImageTargetsRenderer建立一個建構函式。在這個建構函式裡,將Activity作為引數傳遞進來,也在這個建構函式中初始化場景。
public ImageTargetsRenderer(ImageTargets activity){ this.mActivity = activity; world = new World(); world.setAmbientLight(20, 20, 20); sun = new Light(world); sun.setIntensity(250, 250, 250); // Create a texture out of the icon...:-) Texture texture = new Texture(BitmapHelper.rescale(BitmapHelper.convert(mActivity.getResources().getDrawable(R.drawable.ic_launcher)), 64, 64)); TextureManager.getInstance().addTexture("texture", texture); cube = Primitives.getCube(10); cube.calcTextureWrapSpherical(); cube.setTexture("texture"); cube.strip(); cube.build(); world.addObject(cube); cam = world.getCamera(); cam.moveCamera(Camera.CAMERA_MOVEOUT, 50); cam.lookAt(cube.getTransformedCenter()); SimpleVector sv = new SimpleVector(); sv.set(cube.getTransformedCenter()); sv.y -= 100; sv.z -= 100; sun.setPosition(sv); MemoryHelper.compact(); }
然後在ImageTargets.java檔案中,修改ImageTargetRenderer的初始化將activity作為引數傳遞進結構體中。
mRenderer = new ImageTargetsRenderer(this);
mRenderer.mActivity = this;
mGlView.setRenderer(mRenderer);
然後在ImageTargetRenderer類中的onSurfaceChanged方法中,把jpct的framebuffer的初始化程式碼插入進來,同樣也是從jpct的例子中得來。
if (fb != null) {
fb.dispose();
}
fb = new FrameBuffer(width, height);
好了,我們已經初始化場景和framebuffer,下一步就要使用jpct來繪製模型。(我們使用jpct的主要目的就是希望用他來繪製我們的虛擬場景)。需要在onDrawFrame()方法中完成。將下面的方法插入進onDrawFrame()方法中。
world.renderScene(fb);
world.draw(fb);
fb.display();
這裡不需要fb.clear()。因為QCAR的本地openGL程式碼已經清除了framebuffer.如果這裡再清除一次,就會清除攝像頭拍攝的真實場景。
這時,如果你開啟APP,會在真實場景上面看到一個矩形。(當然這個矩形目前還沒有完成註冊,還需要我們計算的攝像頭矩陣)。
這裡我們需要修改原生代碼,即jni檔案中的程式碼。開啟ImageTargets.cpp檔案,到JNIEXPORT void JNICALL Java_com_qualcomm_QCARSamples_ImageTargets_ImageTargetsRenderer_renderFrame(JNIEnv *, jobject)這個方法的實現下。
這裡是標準的OpenGL的程式碼。逐幀迴圈執行的執行緒。在Android中這是一個單獨的執行緒。在這個方法裡,framebuffer被清空,計算得到投影矩陣和模型檢視矩陣,並且繪製模型。
這裡不需要使用Vuforia渲染,渲染的任務交給jPCT-AE即可。刪除一些不必要的語句,最後如下:
{
// Clear color and depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Get the state from QCAR and mark the beginning of a rendering section
QCAR::State state = QCAR::Renderer::getInstance().begin();
// Explicitly render the Video Background
QCAR::Renderer::getInstance().drawVideoBackground();
// Did we find any trackables this frame?
for(int tIdx = 0; tIdx < state.getNumTrackableResults(); tIdx++)
{
// Get the trackable:
const QCAR::TrackableResult* result = state.getTrackableResult(tIdx);
const QCAR::Trackable& trackable = result->getTrackable();
QCAR::Matrix44F modelViewMatrix = QCAR::Tool::convertPose2GLMatrix(result->getPose());
}
QCAR::Renderer::getInstance().end();
}
使用NDK進行編譯。接下來我們需要將native層計算得出的模型檢視矩陣和投影矩陣傳遞到java層。建立瞭如下方法接受從native層傳遞進來的矩陣,它是一個4X4的矩陣。
public void updateModelviewMatrix(float mat[]) {
modelViewMat = mat;
}
由於矩陣(模型檢視矩陣和投影矩陣)是每幀都需要計算和檢測的,所以這個方法也應該迴圈呼叫。所以需要在native層中的renderFrame方法中呼叫該方法。這裡用到Jni程式設計的一些規則,不清楚的同學可以去參考相關資料。
jclass activityClass = env->GetObjectClass(obj); //獲取Activity
jmethodID updateMatrixMethod = env->GetMethodID(activityClass, "updateModelviewMatrix", "([F)V");
接下來就需要將估算的矩陣結果傳遞到java層。
jfloatArray modelviewArray = env->NewFloatArray(16);
for(int tIdx = 0; tIdx < state.getNumTrackableResults(); tIdx++)
{
// Get the trackable:
const QCAR::TrackableResult* result = state.getTrackableResult(tIdx);
const QCAR::Trackable& trackable = result->getTrackable();
QCAR::Matrix44F modelViewMatrix = QCAR::Tool::convertPose2GLMatrix(result->getPose());
SampleUtils::rotatePoseMatrix(90.0f, 1.0f, 0, 0, &modelViewMatrix.data[0]);
QCAR::Matrix44F inverseMV = SampleMath::Matrix44FInverse(modelViewMatrix);
QCAR::Matrix44F invTranspMV = SampleMath::Matrix44FTranspose(inverseMV);
// 將資料傳遞到java層
env->SetFloatArrayRegion(modelviewArray, 0, 16, invTranspMV.data);
env->CallVoidMethod(obj, updateMatrixMethod, modelviewArray);
}
// hide the objects when the targets are not detected
if (state.getNumTrackableResults() == 0) {
float m [] = {
1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,-10000,1
};
env->SetFloatArrayRegion(modelviewArray, 0, 16, m);
env->CallVoidMethod(obj, updateMatrixMethod, modelviewArray);
}
env->DeleteLocalRef(modelviewArray);
這裡對modelViewMatrix矩陣在X軸上進行旋轉180°,因為JPCT的座標系繞X軸旋轉了180°。使用SetFloatArrayRegion將矩陣結果設定成浮點陣列型別。最後通過native層呼叫java層方法updateMatrix將結果向Java層傳遞。
好的,接下來回到Java層,將剛剛從Native層傳遞過來的資料給Camera。public void updateCamera() {
if (modelViewMat != null) {
float[] m = modelViewMat;
final SimpleVector camUp;
if (mActivity.isPortrait()) {
camUp = new SimpleVector(-m[0], -m[1], -m[2]);
} else {
camUp = new SimpleVector(-m[4], -m[5], -m[6]);
}
final SimpleVector camDirection = new SimpleVector(m[8], m[9], m[10]);
final SimpleVector camPosition = new SimpleVector(m[12], m[13], m[14]);
cam.setOrientation(camDirection, camUp);
cam.setPosition(camPosition);
cam.setFOV(fov);
cam.setYFOV(fovy);
}
}
位置和旋轉組成攝像頭的稱作攝像頭的位姿,然而除了這個之外,攝像頭所需要設定的引數遠不止這些,還有FOV,簡稱視場,他也會影響攝像頭所看到的場景,關於更詳細的資訊請看:http://en.wikipedia.org/wiki/Field_of_view
由於不同的裝置具有不同的FOV。這個就和攝像頭的標定有關了。在QCAR庫中提供了計算的函式,包括水平和垂直的FOV,看下面的程式碼。
這裡使用QCAR攝像頭標定的方法,獲取攝像頭的內部物理引數,這個在關於3D模型AR應用中也是必須的。
const QCAR::CameraCalibration& cameraCalibration = QCAR::CameraDevice::getInstance().getCameraCalibration();
QCAR::Vec2F size = cameraCalibration.getSize();
QCAR::Vec2F focalLength = cameraCalibration.getFocalLength();
float fovyRadians = 2 * atan(0.5f * size.data[1] / focalLength.data[1]);
float fovRadians = 2 * atan(0.5f * size.data[0] / focalLength.data[0]);
然後在通過對應的方法將資料上傳:
Java層:
public void setFov(float fov) {
this.fov = fov;
}
public void setFovy(float fovy) {
this.fovy = fovy;
}
Native層:
jmethodID fovMethod = env->GetMethodID(activityClass, "setFov", "(F)V");
jmethodID fovyMethod = env->GetMethodID(activityClass, "setFovy", "(F)V");
env->CallVoidMethod(obj, fovMethod, fovRadians);
env->CallVoidMethod(obj, fovyMethod, fovyRadians);
寫到這裡,基本上整合工作就做完了,可以執行試試效果。
相關推薦
(Android)Vuforia Native版本與jpct-ae結合
AR/VR技術交流群 129340649 Qualcomm的Vuforia引擎是最強大的增強現實引擎之一。將它和JPCT-AE結合是一個很好的想法,它可以讓你的Android裝置實現讓人驚奇的AR場景。 其中在Android端和iOS端的Vuforia Native版本
(Android)react-native更改狀態列文字和圖示顏色
react-native中給的StatusBar元件中並不能更改Android的文字顏色,下面是通過Android原生進行更改的,但是並不適用於所有的Android手機。 1、初始化一個專案做測試。用Android Studio開啟專案的android部分。 在java檔案
React-Native 與原生的3種互動通訊(Android)
前言 最近到新公司,採用React-Native開發App。在某些效能方面有問題或者模組特殊的開發情況,不可避免的需要我們原生開發(Android\IOS)給予前端開發支援。 在為前端書寫模組部分,不可避免的要接觸核心的通訊部分。 大致分為2種情況:
Kubernetes 1.12公佈:Kubelet TLS Bootstrap與Azure虛擬機器規模集(VMSS)迎來通用版本號
今天,我們非常高興地推出Kubernetes 1.12版本號,這也是我們今年以來公佈的第三個版本號。 此次公佈繼續關注內部改進與功能完好。旨在進一步提升與Kubernetes對接時的穩定性。 這一最新版本號亦在安全性與Azure等關鍵功能上做出增
Kubernetes 1.12公布:Kubelet TLS Bootstrap與Azure虛擬機規模集(VMSS)迎來通用版本號
node 2018年 ear 撤銷 開源技術 apiserver als 新版本 Helm 版權聲明:本文為博主原創文章,未經博主同意不得轉載。 https://blog.csdn.net/M2l0ZgSsVc7r69eFdTj/art
windows下配置React-Native(Android)開發環境總結
首先配置環境我們需要用到以下工具: node.js react-native-cli Android Studio JDK(1.8以上) SDK python 1.安裝node.js和react-native-cli命令列工具
SpringCloud進擊 | 四淺出:斷路器與容錯(Hystrix)【Finchley版本】
1.前言 上一節:SpringCloud進擊 | 三淺出:服務消費者(Feign)【Finchley版本】 斷路器:Hystrix 客戶端,字面上理解,就是斷開一端和另一端之間的鏈路。當某個服務單元發生故障之後,通過斷路器的故障監控,向呼叫方返回一個預留的、可處理的備選響應,即服務降
SpringCloud進擊 | 一淺出:服務註冊與發現(Eureka)【Finchley版本】
1.前言 Spring Cloud 已經幫我們實現了服務註冊中心,我們只需要很簡單的幾個步驟就可以完成。關於理論知識,我想大家都已經有不同程度上的瞭解和認識,這裡,我們最後再進行總結。本系列 Spring Cloud 介紹基於 Spring Boot 2.0.5 版本和 Spring C
spring-cloud(一)服務的註冊與發現Eureka(Finchley版本)
spring cloud 為開發人員提供了快速構建分散式系統的一些工具,包括配置管理、服務發現、斷路器、路由、微代理、事件匯流排、全域性鎖、決策競選、分散式會話等等。它執行環境簡單,可以在開發人員的電腦上跑。另外說明spring cloud是基於springboot的,所以需要開發中對springb
react-native 啟動頁設定(android)
使用第三方外掛:react-native-splash-screen 下載地址:https://www.npmjs.com/package/react-native-splash-screen 第一步:安裝下載外掛 1、npm i react-native-splash-screen
二維碼(QRcode)容量的計算與版本
轉載自: https://www.cnblogs.com/feng9exe/p/5995055.html 4.版本資訊:即二維碼的規格,QR碼符號共有40種規格的矩陣(一般為黑白色),從21x21(版本1),到177x177(版本40),每一版本符號比前一版本每邊增加4個模組。
Kubernetes 1.12釋出:Kubelet TLS Bootstrap與Azure虛擬機器規模集(VMSS)迎來通用版本
今天,我們很高興地推出Kubernetes 1.12版本,這也是我們今年以來發布的第三個版本!此
react-native-android-unity(一)react-native加入android原生
本人是做後端php的,對各類語言和方向都有興趣,多而不精。最近公司專案有一個移動端app,決定採用react-native開發,專案中有這麼個要求,要求react-native中嵌入原生頁面,然後原生頁面嵌入unity,並實現原生和unity之前相互通訊,網路查詢資料後實現
Android Studio使用的那些事(三)AS不同版本安裝注意點
繼上篇遷移整理了 Android Studio使用的那些事(二)AS常見錯誤 這篇將整理記錄Android Studio我在使用更新不同版本時候所遇到要注意的點。Android Studio當時的1.2、1.5 我就沒有記錄了,因為當時AS還不夠成熟問題還很多,雖然下載安裝了
FTS資料庫優化(Android)原理與應用詳解(1)
在Android的官方開發文件上,有建議在使用文字類的資料庫全文搜尋(full-text search)時,使用FTS優化查詢速度。有關FTS的介紹文章不多,本文調研整理一下有關知識,供在Android上使用FTS之前參考。 1.什麼是FTS? FTS,即full te
Python網路爬蟲(三):chromdriver.exe與chrome版本對映及下載連結
前言:最近正在學習Python網路爬蟲,學到selenium,需要用到chrome瀏覽器的驅動,但是網上的很多地址都被牆了,而且沒有準確的驅動和chrome版本的對映,很麻煩。現在我已經解決了這些問題,現在把對映和下載連結分享出來。 (一)檢視chrome
Android二維碼掃描開發(一):實現思路與原理
【 回覆“ 1024 ”,送你一個特別推送 】 現在二維碼已經非常普及了,那麼二維碼的掃描與處理也成為了Android開發中的一個必要技能。網上有很多關於Android中二維碼處理的帖子,大都是在講開源框架zxing用法,然後貼貼程式碼就完了,並沒有一個系統的分析和
React-Native 熱更新嘗試(Android)
前言:由於蘋果釋出的ios的一些rn的app存在安全問題,主要就是由於一些第三方的熱更新庫導致的,然而訊息一出就鬧得沸沸揚揚的,導致有些人直接認為“學了大半年的rn白學啦~~!!真是哭笑不得。廢話不多說了,馬上進入我們今天的主題吧。“ 因為一直在做androi
Weex元件與模組封裝(Android)
Weex元件Android Studio配置在AndroidManifest.xml中新增網路許可權等許可權。<uses-permission android:name="android.perm
Android基礎(一):四大元件與另一個重要元件Intent的簡單認識
與其他系統應用程式不同,Android應用程式沒有為應用程式提供一個單獨的應用程式入口(如同沒有mian方法)而是為系統依照需求例項化提供了基本的元件,這就是我之後要講到的Android的四大元件和另