blob: b0a3eae1db73dc4d339ae7c988fc59fafdb4ce5b [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/ui/lib/escher/math/rotations.h"
#include <lib/syslog/cpp/macros.h>
#include <cmath>
#include <glm/gtc/epsilon.hpp>
#include <glm/gtx/matrix_operation.hpp>
namespace escher {
void RotationBetweenVectors(const glm::vec3& u, const glm::vec3& v, glm::quat* rotation) {
// http://lolengine.net/blog/2014/02/24/quaternion-from-two-vectors-final
float norm_u_norm_v = sqrt(dot(u, u) * glm::dot(v, v));
float real_part = norm_u_norm_v + glm::dot(u, v);
glm::vec3 w;
if (real_part < kEpsilon * norm_u_norm_v) {
// If u and v are exactly opposite, rotate 180 degrees around an arbitrary
// orthogonal axis. Axis normalisation can happen later, when we normalise
// the quaternion.
real_part = 0.f;
w = abs(u.x) > abs(u.z) ? glm::vec3(-u.y, u.x, 0.f) : glm::vec3(0.f, -u.z, u.y);
} else {
// Otherwise, build quaternion the standard way.
w = cross(u, v);
}
*rotation = glm::normalize(glm::quat(real_part, w.x, w.y, w.z));
}
} // namespace escher