libalmath  2.8.7.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
bezierautotangent.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Softbank Robotics. All rights reserved.
3  * Use of this source code is governed by a BSD-style license that can be
4  * found in the COPYING file.
5  */
6 
7 #ifndef LIBALMATH_ALMATH_SCENEGRAPH_QIANIM_BEZIERAUTOTANGENT_H
8 #define LIBALMATH_ALMATH_SCENEGRAPH_QIANIM_BEZIERAUTOTANGENT_H
9 
10 #include <almath/api.h>
11 #include <utility>
12 #include <cassert>
13 #include <cmath>
14 #include <type_traits>
15 
16 namespace AL {
17 namespace qianim {
18 
19 // Compute the two tangents of a legacy (xar/qianim v1) bezier auto key.
20 //
21 // pDeltaTime1 is the time between this key and previous key,
22 // pDeltaTime2 is the time between next key and this key.
23 // pDeltaAngle1 is the angle change between this key and previous key,
24 // pDeltaAngle2 is the angle change between next key and this key.
25 //
26 // pDeltaTime1 and pDeltaTime2 shall be non-negative
27 // If the key is not a local extremum (ie. if pDeltaAngle1 * pDeltaAngle2 > 0)
28 // then pDeltaTime1 + pDeltaTime2 shall be positive
29 //
30 // Return the (left tangent, right tangent) pair, where each tangent is
31 // an (abscissa, ordinate) pair.
32 template <typename Scalar,
33  typename std::enable_if<std::is_floating_point<Scalar>::value, int>::type = 0 >
34 std::pair<std::pair<Scalar, Scalar>, std::pair<Scalar, Scalar>>
35 computeBezierAutoTangents(Scalar pDeltaTime1, Scalar pDeltaTime2,
36  Scalar pDeltaAngle1, Scalar pDeltaAngle2) {
37  assert(pDeltaTime1 > -1e-5f);
38  assert(pDeltaTime2 > -1e-5f);
39 
40  const auto alpha = Scalar(1) / 3;
41  auto beta = Scalar(0);
42 
43  if (pDeltaAngle1 * pDeltaAngle2 > 0) {
44  // Key is not a local extremum
45  assert(pDeltaTime1 + pDeltaTime2 > 0);
46  beta = (pDeltaAngle1 + pDeltaAngle2) / (pDeltaTime1 + pDeltaTime2);
47 
48  // avoid overshooting
49  auto tgtHeight = std::abs(alpha * pDeltaTime2 * beta);
50  auto absDeltaAngle = std::abs(pDeltaAngle2);
51  if (tgtHeight > absDeltaAngle) {
52  beta *= absDeltaAngle / tgtHeight;
53  }
54  tgtHeight = std::abs(alpha * pDeltaTime1 * beta);
55  absDeltaAngle = std::abs(pDeltaAngle1);
56  if (tgtHeight > absDeltaAngle) {
57  beta *= absDeltaAngle / tgtHeight;
58  }
59  }
60  return std::make_pair(std::make_pair(-alpha * pDeltaTime1,
61  -alpha * beta * pDeltaTime1),
62  std::make_pair(alpha * pDeltaTime2,
63  alpha * beta * pDeltaTime2));
64 }
65 }
66 }
67 
68 #endif
std::pair< std::pair< Scalar, Scalar >, std::pair< Scalar, Scalar > > computeBezierAutoTangents(Scalar pDeltaTime1, Scalar pDeltaTime2, Scalar pDeltaAngle1, Scalar pDeltaAngle2)