Add DaydreamVR native libraries and services
Upstreaming the main VR system components from master-dreamos-dev
into goog/master.
Bug: None
Test: `m -j32` succeeds. Sailfish boots and basic_vr sample app works
Change-Id: I853015872afc443aecee10411ef2d6b79184d051
diff --git a/libs/vr/libeds/eds_mesh.cpp b/libs/vr/libeds/eds_mesh.cpp
new file mode 100644
index 0000000..2c7dc2f
--- /dev/null
+++ b/libs/vr/libeds/eds_mesh.cpp
@@ -0,0 +1,136 @@
+#include "include/private/dvr/eds_mesh.h"
+
+#include <math.h>
+
+#include <base/logging.h>
+#include <private/dvr/types.h>
+
+namespace {
+
+using android::dvr::EdsVertex;
+using android::dvr::EyeType;
+using android::dvr::DistortionFunction;
+using android::dvr::vec2;
+
+// Computes the vertices for a distortion mesh with resolution |resolution| and
+// distortion provided by |hmd| and stores them in |vertices|.
+static void ComputeDistortionMeshVertices(
+ EdsVertex* vertices, int resolution,
+ const DistortionFunction& distortion_function, EyeType eye) {
+ for (int row = 0; row < resolution; row++) {
+ for (int col = 0; col < resolution; col++) {
+ const float x_norm =
+ static_cast<float>(col) / (static_cast<float>(resolution - 1U));
+ const float y_norm =
+ static_cast<float>(row) / (static_cast<float>(resolution - 1U));
+
+ const vec2 xy_norm(x_norm, y_norm);
+ const size_t index = col * resolution + row;
+
+ // Evaluate distortion function to get the new coordinates for each color
+ // channel. The distortion function returns the new coordinates relative
+ // to a full viewport with 0 <= x <= 1 for each eye.
+ vec2 coords[3];
+ distortion_function(eye, xy_norm, &vertices[index].position, coords);
+
+ // Store distortion mapping in texture coordinates.
+ vertices[index].red_viewport_coords = coords[0];
+ vertices[index].green_viewport_coords = coords[1];
+ vertices[index].blue_viewport_coords = coords[2];
+ }
+ }
+}
+
+// Computes the triangle strip indices for a distortion mesh with resolution
+// |resolution| and stores them in |indices|.
+static void ComputeDistortionMeshIndices(uint16_t* indices, int resolution) {
+ // The following strip method has been used in the Cardboard SDK
+ // (java/com/google/vrtoolkit/cardboard/DistortionRenderer.java) and has
+ // originally been described at:
+ //
+ // http://dan.lecocq.us/wordpress/2009/12/25/triangle-strip-for-grids-a-construction/
+ //
+ // For a grid with 4 rows and 4 columns of vertices, the strip would
+ // look like:
+ // ↻
+ // 0 - 4 - 8 - 12
+ // ↓ ↗ ↓ ↗ ↓ ↗ ↓
+ // 1 - 5 - 9 - 13
+ // ↓ ↖ ↓ ↖ ↓ ↖ ↓
+ // 2 - 6 - 10 - 14
+ // ↓ ↗ ↓ ↗ ↓ ↗ ↓
+ // 3 - 7 - 11 - 15
+ // ↺
+ //
+ // Note the little circular arrows next to 7 and 8 that indicate
+ // repeating that vertex once so as to produce degenerate triangles.
+ //
+ // To facilitate scanline racing, the vertex order is left to right.
+
+ int16_t index_offset = 0;
+ int16_t vertex_offset = 0;
+ for (int row = 0; row < resolution - 1; ++row) {
+ if (row > 0) {
+ indices[index_offset] = indices[index_offset - 1];
+ ++index_offset;
+ }
+ for (int col = 0; col < resolution; ++col) {
+ if (col > 0) {
+ if (row % 2 == 0) {
+ // Move right on even rows.
+ ++vertex_offset;
+ } else {
+ --vertex_offset;
+ }
+ }
+ // A cast to uint16_t is safe here as |vertex_offset| will not drop below
+ // zero in this loop. As col is initially equal to zero |vertex_offset| is
+ // always incremented before being decremented, is initialized to zero and
+ // is only incremented outside of the loop.
+ indices[index_offset++] = static_cast<uint16_t>(vertex_offset);
+ indices[index_offset++] = static_cast<uint16_t>(
+ vertex_offset + static_cast<int16_t>(resolution));
+ }
+ vertex_offset =
+ static_cast<int16_t>(static_cast<int>(resolution) + vertex_offset);
+ }
+}
+
+} // anonymous namespace
+
+namespace android {
+namespace dvr {
+
+// Builds a distortion mesh of resolution |resolution| using the distortion
+// provided by |hmd| for |eye|.
+EdsMesh BuildDistortionMesh(EyeType eye, int resolution,
+ const DistortionFunction& distortion_function) {
+ CHECK_GT(resolution, 2);
+
+ // Number of indices produced by the strip method
+ // (see comment in ComputeDistortionMeshIndices):
+ //
+ // 1 vertex per triangle
+ // 2 triangles per quad, (rows - 1) * (cols - 1) quads
+ // 2 vertices at the start of each row for the first triangle
+ // 1 extra vertex per row (except first and last) for a
+ // degenerate triangle
+ //
+ const uint16_t index_count =
+ static_cast<uint16_t>(resolution * (2 * resolution - 1U) - 2U);
+ const uint16_t vertex_count = static_cast<uint16_t>(resolution * resolution);
+
+ EdsMesh mesh;
+ mesh.vertices.resize(vertex_count);
+ mesh.indices.resize(index_count);
+
+ // Populate vertex and index buffer.
+ ComputeDistortionMeshVertices(&mesh.vertices[0], resolution,
+ distortion_function, eye);
+ ComputeDistortionMeshIndices(&mesh.indices[0], resolution);
+
+ return mesh;
+}
+
+} // namespace dvr
+} // namespace android