/* * Copyright 2016 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.projecttango.rajawali.renderables; import android.graphics.Color; import org.rajawali3d.materials.Material; import java.nio.FloatBuffer; import com.projecttango.rajawali.renderables.primitives.Points; /** * Renders a point cloud using colors to indicate distance to the depth sensor. * Coloring is based on the light spectrum: closest points are in red, farthest in violet. */ public class PointCloud extends Points { // Maximum depth range used to calculate coloring (min = 0) public static final float CLOUD_MAX_Z = 5; private float[] mColorArray; private final int[] mPalette; public static final int PALETTE_SIZE = 360; public static final float HUE_BEGIN = 0; public static final float HUE_END = 320; public PointCloud(int maxPoints) { super(maxPoints, true); mPalette = createPalette(); mColorArray = new float[maxPoints * 4]; Material m = new Material(); m.useVertexColors(true); setMaterial(m); } /** * Pre-calculate a palette to be used to translate between point distance and RGB color. */ private int[] createPalette() { int[] palette = new int[PALETTE_SIZE]; float[] hsv = new float[3]; hsv[1] = hsv[2] = 1; for (int i = 0; i < PALETTE_SIZE; i++) { hsv[0] = (HUE_END - HUE_BEGIN) * i / PALETTE_SIZE + HUE_BEGIN; palette[i] = Color.HSVToColor(hsv); } return palette; } /** * Calculate the right color for each point in the point cloud. */ private void calculateColors(int pointCount, FloatBuffer pointCloudBuffer) { float[] points = new float[pointCount * 3]; pointCloudBuffer.rewind(); pointCloudBuffer.get(points); pointCloudBuffer.rewind(); int color; int colorIndex; float z; for (int i = 0; i < pointCount; i++) { z = points[i * 3 + 2]; colorIndex = (int) Math.min(z / CLOUD_MAX_Z * mPalette.length, mPalette.length - 1); colorIndex = Math.max(colorIndex, 0); color = mPalette[colorIndex]; mColorArray[i * 4] = Color.red(color) / 255f; mColorArray[i * 4 + 1] = Color.green(color) / 255f; mColorArray[i * 4 + 2] = Color.blue(color) / 255f; mColorArray[i * 4 + 3] = Color.alpha(color) / 255f; } } /** * Update the points and colors in the point cloud. */ public void updateCloud(int pointCount, FloatBuffer pointBuffer) { calculateColors(pointCount, pointBuffer); updatePoints(pointCount, pointBuffer, mColorArray); } }