HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
evaluator.h
Go to the documentation of this file.
1 //
2 // Copyright 2023 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 
25 #ifndef PXR_BASE_TS_EVALUATOR_H
26 #define PXR_BASE_TS_EVALUATOR_H
27 
28 #include "pxr/pxr.h"
29 #include "pxr/base/ts/evalCache.h"
30 #include "pxr/base/ts/spline.h"
31 #include "pxr/base/ts/types.h"
32 
33 #include "pxr/base/trace/trace.h"
34 
35 #include <vector>
36 
38 
39 /// \class TsEvaluator
40 /// \brief Opaque interface to a spline for evaluations using cached segments.
41 ///
42 /// Use this evaluator when performing many evaluations on an unchanging
43 /// TsSpline whose knots support tangents (e.g., Bezier splines). Evals on
44 /// this class are required to be thread-safe.
45 ///
46 template <typename T>
47 class TsEvaluator {
48 
49 public:
50 
51  /// Default constructor; falls back to empty spline.
52  TsEvaluator();
53 
54  /// Constructs the evaluator and its caches for the given spline.
56 
57  /// Evaluates the spline at the given time. Note that left side evals do not
58  /// benefit from the cached segments.
59  T Eval(const TsTime &time, TsSide side=TsRight) const;
60 
61 private:
62 
63  // Vector of typed Ts_EvalCaches, one for each Bezier segment in the
64  // spline.
65  std::vector<std::shared_ptr<Ts_EvalCache<T> > > _segments;
66 
67  // The spline being evaluated.
68  TsSpline _spline;
69 };
70 
71 template <typename T>
73 {
74 }
75 
76 template <typename T>
78 _spline(spline)
79 {
81 
82  if (spline.size() > 1) {
83 
84  // Only set up eval caches when there are Bezier segments.
85  bool bezier = false;
86  for (const TsKeyFrame &kf : spline) {
87  if (kf.GetKnotType() == TsKnotBezier) {
88  bezier = true;
89  break;
90  }
91  }
92  if (!bezier) {
93  return;
94  }
95 
96  _segments.reserve(spline.size() - 1);
97 
98  TF_FOR_ALL(splItr, spline) {
99 
100  // Create and store an eval cache for each segment (defined by a
101  // pair of adjacent keyframes) of the spline.
102 
103  TsSpline::const_iterator iAfterTime = splItr;
104  iAfterTime++;
105 
106  if (iAfterTime == spline.end()) {
107  break;
108  }
109 
110  std::shared_ptr<Ts_EvalCache<T> > segmentCache =
111  Ts_EvalCache<T>::New(*splItr, *iAfterTime);
112 
113  if (TF_VERIFY(segmentCache)) {
114  _segments.push_back(segmentCache);
115  }
116  }
117 
118  }
119 }
120 
121 template <typename T>
122 T
124  TsSide side) const
125 {
126 
127  // Only right-side evals can benefit from cached segments.
128  if (!_segments.empty() && side == TsRight) {
129 
130  // Only use eval caches for times that are between the authored knots on
131  // the spline. Boundary extrapolation cases are evaluated directly.
132  if (time >= _spline.begin()->GetTime() &&
133  time <= _spline.rbegin()->GetTime()) {
134 
135  // Get the closest keyframe <= the requested time.
136  TsSpline::const_iterator sample = _spline.lower_bound(time);
137  if (TF_VERIFY(sample != _spline.end())) {
138 
139  // We will index into the _segments vector using the iterator
140  // offset of the given sample. We need another decrement if our
141  // sample is > than the requested time (we want the requested
142  // time to be in between the two keyframes contained in the eval
143  // cache entry.
144  size_t idx = sample - _spline.begin();
145  if (sample->GetTime() > time && TF_VERIFY(idx > 0)) {
146  idx--;
147  }
148 
149  if (TF_VERIFY(idx < _segments.size())
150  && TF_VERIFY(_segments[idx])) {
151  return _segments[idx]->TypedEval(time);
152  }
153  }
154  }
155  }
156 
157  // If we did not get a cache hit, evaluate directly on the spline.
158  if (!_spline.empty()) {
159  return _spline.Eval(time).template Get<T>();
160  }
161 
162  // If we're evaluating an empty spline, fall back to zero.
163  return TsTraits<T>::zero;
164 }
165 
167 
168 #endif
GT_API const UT_StringHolder time
A Bezier knot.
Definition: types.h:67
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat< T > spline(const Quat< T > &q0, const Quat< T > &q1, const Quat< T > &q2, const Quat< T > &q3, T t) IMATH_NOEXCEPT
Definition: ImathQuat.h:576
Definition: types.h:92
T Eval(const TsTime &time, TsSide side=TsRight) const
Definition: evaluator.h:123
#define TRACE_FUNCTION()
Definition: trace.h:43
Specifies the value of an TsSpline object at a particular point in time.
Definition: keyFrame.h:66
Opaque interface to a spline for evaluations using cached segments.
Definition: evaluator.h:47
PXR_NAMESPACE_OPEN_SCOPE typedef double TsTime
The time type used by Ts.
Definition: types.h:57
TsSide
Dual-value keyframe side.
Definition: types.h:90
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1432
TS_API size_t size() const
Returns the number of KeyFrames in this spline.
Definition: spline.h:506
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91
TsKeyFrameMap::const_iterator const_iterator
Definition: spline.h:486
TsEvaluator()
Default constructor; falls back to empty spline.
Definition: evaluator.h:72
#define TF_FOR_ALL(iter, c)
Definition: iterator.h:390