這兩天簡單看了下 java_point_cloud_example 工程的代碼,作此筆記,以備日後查閱。
源碼基於 Eisa 版本。
demo 效果
第一張圖是由 TangoUX 控制的,是一個鋪滿全屏的 com.google.atap.tango.ux.TangoUxLayout,相當於普通 app 裏面的 loading 界面。
第二張圖中的棱錐代表設備,不同顏色的點表示離設備不同距離的點雲,紅色的最近。
晃動設備,棱錐的角度會隨着設備變化。
核心代碼
有兩個核心點:
- 既然能在屏幕上用不同的顏色表示不同的座標,那麼 Tango 肯定是獲取了點雲的座標和距離信息,然後再映射到屏幕上的座標系中;
- 棱錐能隨着設備而擺動,說明代碼裏面肯定有獲取設備 Pose 數據的地方,通過 Pose 裏面的 orientation 信息來控制棱錐的擺動;
根據上述兩個假設,在代碼可中可以找到:
// more code
final double averageDepth = getAveragedDepth(pointCloud.points,
pointCloud.numPoints);
// more code
private float getAveragedDepth(FloatBuffer pointCloudBuffer, int numPoints) {
float totalZ = 0;
float averageZ = 0;
if (numPoints != 0) {
int numFloats = 4 * numPoints;
for (int i = 2; i < numFloats; i = i + 4) {
totalZ = totalZ + pointCloudBuffer.get(i);
}
averageZ = totalZ / numPoints;
}
return averageZ;
}
pointCloudBuffer 裏面是個四元組,查閱 文檔 可以得知,每個四元組都是一個 (x, y, z, c)。
public class TangoPointCloudData implements Parcelable {
public double timestamp;
public int numPoints;
public FloatBuffer points;
}
3個核心字段:
- timestamp,獲得4元組的時間戳;
- numPoints,4元組的數量;
- points,4元組集合,(x, y, z, c),豎直方向放置設備時,x 爲正表示用戶的右手方向,y 爲正表示屏幕底部方向,z 爲正表示攝像頭焦距方向且垂直於攝像頭平面,近似取 z 爲某點距離,c 爲置信係數,區間[0, 1],1 表示完全可信;
拿到點雲的數據之後,在 PointCloud 類裏面做映射計算,將點雲座標映射成不同顏色點的座標。從而顯示在屏幕上。
至於第二個假設,同樣看代碼:
TangoPoseData lastFramePose = TangoSupport.getPoseAtTime(0,TangoPoseData.COORDINATE_FRAME_START_OF_SERVICE, TangoPoseData.COORDINATE_FRAME_DEVICE, TangoSupport.TANGO_SUPPORT_ENGINE_OPENGL, mDisplayRotation);
mRenderer.updateCameraPose(lastFramePose);
通過這種方式來獲取 Pose 數據,然後更新愣頭進行實現角度變化。
上面的點就像一條隔板,把 Tango 相關代碼和 Rajawali 代碼隔離開來。拿到 Tango 數據之後,更新 3D 虛擬圖像的操作就完全交由 Rajawali 來做了,與 Tango 無關了。
Rajawali 類
Material
材質,用來定義 3D 模型的視覺效果,比如光照、顏色、高亮等。
Texture
紋理,3D 模型的表面,比如給球體覆蓋一個世界地圖。
Sphere
球體。
Phong
一種簡單的光照模型。
DirectionalLight
光照
Grid
工程自定義網格類,用於第一人稱視角展示網格。
FrustumAxes
工程自定義棱錐類,用於表示設備。
Points
自定義三位點類。
PointCloud
工程自定義類,代表所有的顏色點。Palette:調色板。
Render
Rajawali 工程中繼承 RajawaliRenderer,重寫 initScene() 和 onRender() 方法。在前者中加入 3D 模型,在後者中加入動畫效果。
待解決
Rajawali 裏面的 Camera 類代表什麼,跟 Tango 設備的 Camera 是什麼關係?這是一個 virtual camera?
camera.setPosition() 和 camera.setOrientation() 又是什麼作用?