这两天简单看了下 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() 又是什么作用?