All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
interpolators.h
1 //
2 // Copyright 2016 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 #ifndef USD_INTERPOLATORS_H
25 #define USD_INTERPOLATORS_H
26 
27 #include "pxr/pxr.h"
28 #include "pxr/usd/usd/common.h"
29 #include "pxr/usd/usd/clip.h"
30 #include "pxr/usd/usd/valueUtils.h"
31 #include "pxr/usd/sdf/layer.h"
32 #include "pxr/base/gf/math.h"
33 
34 PXR_NAMESPACE_OPEN_SCOPE
35 
36 class UsdAttribute;
37 
44 class Usd_InterpolatorBase
45 {
46 public:
47  virtual bool Interpolate(
48  const SdfLayerRefPtr& layer, const SdfPath& path,
49  double time, double lower, double upper) = 0;
50  virtual bool Interpolate(
51  const Usd_ClipRefPtr& clip, const SdfPath& path,
52  double time, double lower, double upper) = 0;
53 };
54 
60 class Usd_NullInterpolator
61  : public Usd_InterpolatorBase
62 {
63 public:
64  virtual bool Interpolate(
65  const SdfLayerRefPtr& layer, const SdfPath& path,
66  double time, double lower, double upper) final
67  {
68  return false;
69  }
70 
71  virtual bool Interpolate(
72  const Usd_ClipRefPtr& clip, const SdfPath& path,
73  double time, double lower, double upper) final
74  {
75  return false;
76  }
77 };
78 
87 class Usd_UntypedInterpolator
88  : public Usd_InterpolatorBase
89 {
90 public:
91  Usd_UntypedInterpolator(const UsdAttribute& attr, VtValue* result)
92  : _attr(attr)
93  , _result(result)
94  {
95  }
96 
97  virtual bool Interpolate(
98  const SdfLayerRefPtr& layer, const SdfPath& path,
99  double time, double lower, double upper) final;
100 
101  virtual bool Interpolate(
102  const Usd_ClipRefPtr& clip, const SdfPath& path,
103  double time, double lower, double upper) final;
104 
105 private:
106  template <class Src>
107  bool _Interpolate(
108  const Src& src, const SdfPath& path,
109  double time, double lower, double upper);
110 
111 private:
112  const UsdAttribute& _attr;
113  VtValue* _result;
114 };
115 
125 template <class T>
126 class Usd_HeldInterpolator
127  : public Usd_InterpolatorBase
128 {
129 public:
130  Usd_HeldInterpolator(T* result)
131  : _result(result)
132  {
133  }
134 
135  virtual bool Interpolate(
136  const SdfLayerRefPtr& layer, const SdfPath& path,
137  double time, double lower, double upper) final
138  {
139  return layer->QueryTimeSample(path, lower, _result);
140  }
141 
142  virtual bool Interpolate(
143  const Usd_ClipRefPtr& clip, const SdfPath& path,
144  double time, double lower, double upper) final
145  {
146  return clip->QueryTimeSample(path, lower, this, _result);
147  }
148 
149 private:
150  T* _result;
151 };
152 
153 template <class T>
154 inline T
155 Usd_Lerp(double alpha, const T &lower, const T &upper)
156 {
157  return GfLerp(alpha, lower, upper);
158 }
159 
160 inline GfQuath
161 Usd_Lerp(double alpha, const GfQuath &lower, const GfQuath &upper)
162 {
163  return GfSlerp(alpha, lower, upper);
164 }
165 
166 inline GfQuatf
167 Usd_Lerp(double alpha, const GfQuatf &lower, const GfQuatf &upper)
168 {
169  return GfSlerp(alpha, lower, upper);
170 }
171 
172 inline GfQuatd
173 Usd_Lerp(double alpha, const GfQuatd &lower, const GfQuatd &upper)
174 {
175  return GfSlerp(alpha, lower, upper);
176 }
177 
185 template <class T>
186 class Usd_LinearInterpolator
187  : public Usd_InterpolatorBase
188 {
189 public:
190  Usd_LinearInterpolator(T* result)
191  : _result(result)
192  {
193  }
194 
195  virtual bool Interpolate(
196  const SdfLayerRefPtr& layer, const SdfPath& path,
197  double time, double lower, double upper) final
198  {
199  return _Interpolate(layer, path, time, lower, upper);
200  }
201 
202  virtual bool Interpolate(
203  const Usd_ClipRefPtr& clip, const SdfPath& path,
204  double time, double lower, double upper) final
205  {
206  return _Interpolate(clip, path, time, lower, upper);
207  }
208 
209 private:
210  template <class Src>
211  bool _Interpolate(
212  const Src& src, const SdfPath& path,
213  double time, double lower, double upper)
214  {
215  T lowerValue, upperValue;
216 
217  // In the presence of a value block we use held interpolation.
218  // We know that a failed call to QueryTimeSample is a block
219  // because the provided time samples should all have valid values.
220  // So this call fails because our <T> is not an SdfValueBlock,
221  // which is the type of the contained value.
222  Usd_LinearInterpolator<T> lowerInterpolator(&lowerValue);
223  Usd_LinearInterpolator<T> upperInterpolator(&upperValue);
224 
225  if (!Usd_QueryTimeSample(
226  src, path, lower, &lowerInterpolator, &lowerValue)) {
227  return false;
228  }
229  else if (!Usd_QueryTimeSample(
230  src, path, upper, &upperInterpolator, &upperValue)) {
231  upperValue = lowerValue;
232  }
233 
234  const double parametricTime = (time - lower) / (upper - lower);
235  *_result = Usd_Lerp(parametricTime, lowerValue, upperValue);
236  return true;
237  }
238 
239 private:
240  T* _result;
241 };
242 
243 // Specialization to linearly interpolate each element for
244 // array types.
245 template <class T>
246 class Usd_LinearInterpolator<VtArray<T> >
247  : public Usd_InterpolatorBase
248 {
249 public:
250  Usd_LinearInterpolator(VtArray<T>* result)
251  : _result(result)
252  {
253  }
254 
255  virtual bool Interpolate(
256  const SdfLayerRefPtr& layer, const SdfPath& path,
257  double time, double lower, double upper) final
258  {
259  return _Interpolate(layer, path, time, lower, upper);
260  }
261 
262  virtual bool Interpolate(
263  const Usd_ClipRefPtr& clip, const SdfPath& path,
264  double time, double lower, double upper) final
265  {
266  return _Interpolate(clip, path, time, lower, upper);
267  }
268 
269 private:
270  template <class Src>
271  bool _Interpolate(
272  const Src& src, const SdfPath& path,
273  double time, double lower, double upper)
274  {
275  VtArray<T> lowerValue, upperValue;
276 
277  // In the presence of a value block we use held interpolation.
278  // We know that a failed call to QueryTimeSample is a block
279  // because the provided time samples should all have valid values.
280  // So this call fails because our <T> is not an SdfValueBlock,
281  // which is the type of the contained value.
282  Usd_LinearInterpolator<VtArray<T> > lowerInterpolator(&lowerValue);
283  Usd_LinearInterpolator<VtArray<T> > upperInterpolator(&upperValue);
284 
285  if (!Usd_QueryTimeSample(
286  src, path, lower, &lowerInterpolator, &lowerValue)) {
287  return false;
288  }
289  else if (!Usd_QueryTimeSample(
290  src, path, upper, &upperInterpolator, &upperValue)) {
291  upperValue = lowerValue;
292  }
293 
294  _result->swap(lowerValue);
295 
296  // Fall back to held interpolation (_result is set to lowerValue above)
297  // if sizes don't match. We don't consider this an error because
298  // that would be too restrictive. Consumers will be responsible for
299  // implementing their own interpolation in cases where this occurs
300  // (e.g. meshes with varying topology)
301  if (_result->size() != upperValue.size()) {
302  return true;
303  }
304 
305  const double parametricTime = (time - lower) / (upper - lower);
306  if (parametricTime == 0.0) {
307  // do nothing.
308  }
309  else if (parametricTime == 1.0) {
310  // just swap the upper value in.
311  _result->swap(upperValue);
312  }
313  else {
314  // must actually calculate interpolated values.
315  T *rptr = _result->data();
316  for (size_t i = 0, j = _result->size(); i != j; ++i) {
317  rptr[i] = Usd_Lerp(parametricTime, rptr[i], upperValue[i]);
318  }
319  }
320 
321  return true;
322  }
323 
324 private:
325  VtArray<T>* _result;
326 };
327 
332 template <class Src, class T>
333 inline bool
334 Usd_GetOrInterpolateValue(
335  const Src& src, const SdfPath& path,
336  double time, double lower, double upper,
337  Usd_InterpolatorBase* interpolator, T* result)
338 {
339  if (GfIsClose(lower, upper, /* epsilon = */ 1e-6)) {
340  bool queryResult = Usd_QueryTimeSample(
341  src, path, lower, interpolator, result);
342  return queryResult && (!Usd_ClearValueIfBlocked(result));
343  }
344 
345  return interpolator->Interpolate(src, path, time, lower, upper);
346 }
347 
348 PXR_NAMESPACE_CLOSE_SCOPE
349 
350 #endif // USD_INTERPOLATORS_H
Basic type: a quaternion, a complex number with a real coefficient and three imaginary coefficients...
Definition: quath.h:61
bool GfIsClose(double a, double b, double epsilon)
Returns true if a and b are with epsilon of each other.
Definition: math.h:39
Scenegraph object for authoring and retrieving numeric, string, and array valued data, sampled over time.
Definition: attribute.h:176
Basic type: a quaternion, a complex number with a real coefficient and three imaginary coefficients...
Definition: quatf.h:60
GF_API GfQuatd GfSlerp(double alpha, const GfQuatd &q0, const GfQuatd &q1)
Spherically linearly interpolate between q0 and q1.
T GfLerp(double alpha, const T &a, const T &b)
Linear interpolation function.
Definition: math.h:190
size_t size() const
Return the total number of elements in this array.
Definition: array.h:428
Represents an arbitrary dimensional rectangular container class.
Definition: array.h:193
A path value used to locate objects in layers or scenegraphs.
Definition: path.h:287
void swap(VtArray &other)
Swap the contents of this array with other.
Definition: array.h:585
Basic type: a quaternion, a complex number with a real coefficient and three imaginary coefficients...
Definition: quatd.h:60
Provides a container which may hold any type, and provides introspection and iteration over array typ...
Definition: value.h:182