chromium/device/vr/android/arcore/arcore_math_utils.cc

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "device/vr/android/arcore/arcore_math_utils.h"

#include "base/check_op.h"
#include "base/logging.h"

namespace device {

gfx::Transform MatrixFromTransformedPoints(const base::span<const float> uvs) {
  DCHECK_GE(uvs.size(), 6u);

  //
  // In order to compute the matrix, we need to solve the following 3 equations
  // for 6 unknowns:
  //
  //  | a b c |   | u |   | u' |
  //  | d e f | * | v | = | v' |
  //  | 0 0 1 |   | 1 |   | 1  |
  //
  //  where 3 (u', v') pairs are passed in as an input to the method, and (u,v)
  //  pairs are assumed to come from kInputCoordinatesForTransform.
  //
  // 1. From substituting point (0, 0) for (u,v), we get:
  //
  //  c = uvs[0]
  //  f = uvs[1]
  //
  // 2. From substituting point (1, 0) for (u,v), we get:
  //
  //  a + c = uvs[2]  ->  a = uvs[2] - uvs[0]
  //  d + f = uvs[3]  ->  d = uvs[3] - uvs[1]
  //
  // 3. From substituting point (0, 1) for (u,v), we get:
  //
  //  b + c = uvs[4]  ->  b = uvs[4] - uvs[0]
  //  e + f = uvs[5]  ->  e = uvs[5] - uvs[1]
  //

  DVLOG(3) << __func__ << ": uvs=[ " << uvs[0] << " , " << uvs[1] << " , "
           << uvs[2] << " , " << uvs[3] << " , " << uvs[4] << " , " << uvs[5]
           << " ]";

  // Assumes that |uvs| is the result of transforming the display coordinates
  // from kInputCoordinatesForTransform - size must match.
  DCHECK_EQ(uvs.size(), kInputCoordinatesForTransform.size());

  // Transform initializes to the identity matrix and then is modified by uvs.
  gfx::Transform result;
  result.set_rc(0, 0, uvs[2] - uvs[0]);
  result.set_rc(0, 1, uvs[4] - uvs[0]);
  result.set_rc(0, 3, uvs[0]);

  result.set_rc(1, 0, uvs[3] - uvs[1]);
  result.set_rc(1, 1, uvs[5] - uvs[1]);
  result.set_rc(1, 3, uvs[1]);

  return result;
}

}  // namespace device