blob: 2c7dc2f3447c23f55bae666714dbbf91586b5f26 [file] [log] [blame]
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08001#include "include/private/dvr/eds_mesh.h"
2
3#include <math.h>
4
5#include <base/logging.h>
6#include <private/dvr/types.h>
7
8namespace {
9
10using android::dvr::EdsVertex;
11using android::dvr::EyeType;
12using android::dvr::DistortionFunction;
13using android::dvr::vec2;
14
15// Computes the vertices for a distortion mesh with resolution |resolution| and
16// distortion provided by |hmd| and stores them in |vertices|.
17static void ComputeDistortionMeshVertices(
18 EdsVertex* vertices, int resolution,
19 const DistortionFunction& distortion_function, EyeType eye) {
20 for (int row = 0; row < resolution; row++) {
21 for (int col = 0; col < resolution; col++) {
22 const float x_norm =
23 static_cast<float>(col) / (static_cast<float>(resolution - 1U));
24 const float y_norm =
25 static_cast<float>(row) / (static_cast<float>(resolution - 1U));
26
27 const vec2 xy_norm(x_norm, y_norm);
28 const size_t index = col * resolution + row;
29
30 // Evaluate distortion function to get the new coordinates for each color
31 // channel. The distortion function returns the new coordinates relative
32 // to a full viewport with 0 <= x <= 1 for each eye.
33 vec2 coords[3];
34 distortion_function(eye, xy_norm, &vertices[index].position, coords);
35
36 // Store distortion mapping in texture coordinates.
37 vertices[index].red_viewport_coords = coords[0];
38 vertices[index].green_viewport_coords = coords[1];
39 vertices[index].blue_viewport_coords = coords[2];
40 }
41 }
42}
43
44// Computes the triangle strip indices for a distortion mesh with resolution
45// |resolution| and stores them in |indices|.
46static void ComputeDistortionMeshIndices(uint16_t* indices, int resolution) {
47 // The following strip method has been used in the Cardboard SDK
48 // (java/com/google/vrtoolkit/cardboard/DistortionRenderer.java) and has
49 // originally been described at:
50 //
51 // http://dan.lecocq.us/wordpress/2009/12/25/triangle-strip-for-grids-a-construction/
52 //
53 // For a grid with 4 rows and 4 columns of vertices, the strip would
54 // look like:
55 // ↻
56 // 0 - 4 - 8 - 12
57 // ↓ ↗ ↓ ↗ ↓ ↗ ↓
58 // 1 - 5 - 9 - 13
59 // ↓ ↖ ↓ ↖ ↓ ↖ ↓
60 // 2 - 6 - 10 - 14
61 // ↓ ↗ ↓ ↗ ↓ ↗ ↓
62 // 3 - 7 - 11 - 15
63 // ↺
64 //
65 // Note the little circular arrows next to 7 and 8 that indicate
66 // repeating that vertex once so as to produce degenerate triangles.
67 //
68 // To facilitate scanline racing, the vertex order is left to right.
69
70 int16_t index_offset = 0;
71 int16_t vertex_offset = 0;
72 for (int row = 0; row < resolution - 1; ++row) {
73 if (row > 0) {
74 indices[index_offset] = indices[index_offset - 1];
75 ++index_offset;
76 }
77 for (int col = 0; col < resolution; ++col) {
78 if (col > 0) {
79 if (row % 2 == 0) {
80 // Move right on even rows.
81 ++vertex_offset;
82 } else {
83 --vertex_offset;
84 }
85 }
86 // A cast to uint16_t is safe here as |vertex_offset| will not drop below
87 // zero in this loop. As col is initially equal to zero |vertex_offset| is
88 // always incremented before being decremented, is initialized to zero and
89 // is only incremented outside of the loop.
90 indices[index_offset++] = static_cast<uint16_t>(vertex_offset);
91 indices[index_offset++] = static_cast<uint16_t>(
92 vertex_offset + static_cast<int16_t>(resolution));
93 }
94 vertex_offset =
95 static_cast<int16_t>(static_cast<int>(resolution) + vertex_offset);
96 }
97}
98
99} // anonymous namespace
100
101namespace android {
102namespace dvr {
103
104// Builds a distortion mesh of resolution |resolution| using the distortion
105// provided by |hmd| for |eye|.
106EdsMesh BuildDistortionMesh(EyeType eye, int resolution,
107 const DistortionFunction& distortion_function) {
108 CHECK_GT(resolution, 2);
109
110 // Number of indices produced by the strip method
111 // (see comment in ComputeDistortionMeshIndices):
112 //
113 // 1 vertex per triangle
114 // 2 triangles per quad, (rows - 1) * (cols - 1) quads
115 // 2 vertices at the start of each row for the first triangle
116 // 1 extra vertex per row (except first and last) for a
117 // degenerate triangle
118 //
119 const uint16_t index_count =
120 static_cast<uint16_t>(resolution * (2 * resolution - 1U) - 2U);
121 const uint16_t vertex_count = static_cast<uint16_t>(resolution * resolution);
122
123 EdsMesh mesh;
124 mesh.vertices.resize(vertex_count);
125 mesh.indices.resize(index_count);
126
127 // Populate vertex and index buffer.
128 ComputeDistortionMeshVertices(&mesh.vertices[0], resolution,
129 distortion_function, eye);
130 ComputeDistortionMeshIndices(&mesh.indices[0], resolution);
131
132 return mesh;
133}
134
135} // namespace dvr
136} // namespace android