Overte C++ Documentation
AnimChain.h
1 //
2 // AnimChain.h
3 //
4 // Created by Anthony J. Thibault on 7/16/2018.
5 // Copyright (c) 2018 High Fidelity, Inc. All rights reserved.
6 //
7 // Distributed under the Apache License, Version 2.0.
8 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
9 //
10 
11 #ifndef hifi_AnimChain
12 #define hifi_AnimChain
13 
14 #include <vector>
15 #include <glm/glm.hpp>
16 #include <glm/gtc/quaternion.hpp>
17 
18 #include <DebugDraw.h>
19 
20 template <int N>
21 class AnimChainT {
22 
23 public:
24  AnimChainT() {}
25 
26  AnimChainT(const AnimChainT& orig) {
27  _top = orig._top;
28  for (int i = 0; i < _top; i++) {
29  _chain[i] = orig._chain[i];
30  }
31  }
32 
33  AnimChainT& operator=(const AnimChainT& orig) {
34  _top = orig._top;
35  for (int i = 0; i < _top; i++) {
36  _chain[i] = orig._chain[i];
37  }
38  return *this;
39  }
40 
41  bool buildFromRelativePoses(const AnimSkeleton::ConstPointer& skeleton, const AnimPoseVec& relativePoses, int tipIndex) {
42  _top = 0;
43  // iterate through the skeleton parents, from the tip to the base, copying over relativePoses into the chain.
44  for (int jointIndex = tipIndex; jointIndex != -1; jointIndex = skeleton->getParentIndex(jointIndex)) {
45  if (_top >= N) {
46  assert(_top < N);
47  // stack overflow
48  return false;
49  }
50  _chain[_top].relativePose = relativePoses[jointIndex];
51  _chain[_top].jointIndex = jointIndex;
52  _chain[_top].dirty = true;
53  _top++;
54  }
55 
56  buildDirtyAbsolutePoses();
57 
58  return true;
59  }
60 
61  const AnimPose& getAbsolutePoseFromJointIndex(int jointIndex) const {
62  for (int i = 0; i < _top; i++) {
63  if (_chain[i].jointIndex == jointIndex) {
64  return _chain[i].absolutePose;
65  }
66  }
67  return AnimPose::identity;
68  }
69 
70  bool setRelativePoseAtJointIndex(int jointIndex, const AnimPose& relativePose) {
71  bool foundIndex = false;
72  for (int i = _top - 1; i >= 0; i--) {
73  if (_chain[i].jointIndex == jointIndex) {
74  _chain[i].relativePose = relativePose;
75  foundIndex = true;
76  }
77  // all child absolute poses are now dirty
78  if (foundIndex) {
79  _chain[i].dirty = true;
80  }
81  }
82  return foundIndex;
83  }
84 
85  void buildDirtyAbsolutePoses() {
86  // the relative and absolute pose is the same for the base of the chain.
87  _chain[_top - 1].absolutePose = _chain[_top - 1].relativePose;
88  _chain[_top - 1].dirty = false;
89 
90  // iterate chain from base to tip, concatinating the relative poses to build the absolute poses.
91  for (int i = _top - 1; i > 0; i--) {
92  AnimChainElem& parent = _chain[i];
93  AnimChainElem& child = _chain[i - 1];
94 
95  if (child.dirty) {
96  child.absolutePose = parent.absolutePose * child.relativePose;
97  child.dirty = false;
98  }
99  }
100  }
101 
102  void blend(const AnimChainT& srcChain, float alpha) {
103  // make sure chains have same lengths
104  assert(srcChain._top == _top);
105  if (srcChain._top != _top) {
106  return;
107  }
108 
109  // only blend the relative poses
110  for (int i = 0; i < _top; i++) {
111  _chain[i].relativePose.blend(srcChain._chain[i].relativePose, alpha);
112  _chain[i].dirty = true;
113  }
114  }
115 
116  int size() const {
117  return _top;
118  }
119 
120  void outputRelativePoses(AnimPoseVec& relativePoses) {
121  for (int i = 0; i < _top; i++) {
122  relativePoses[_chain[i].jointIndex] = _chain[i].relativePose;
123  }
124  }
125 
126  void debugDraw(const glm::mat4& geomToWorldMat, const glm::vec4& color) const {
127  for (int i = 1; i < _top; i++) {
128  glm::vec3 start = transformPoint(geomToWorldMat, _chain[i - 1].absolutePose.trans());
129  glm::vec3 end = transformPoint(geomToWorldMat, _chain[i].absolutePose.trans());
130  DebugDraw::getInstance().drawRay(start, end, color);
131  }
132  }
133 
134  void dump() const {
135  for (int i = 0; i < _top; i++) {
136  qWarning() << "AJT: AnimPoseElem[" << i << "]";
137  qWarning() << "AJT: relPose =" << _chain[i].relativePose;
138  qWarning() << "AJT: absPose =" << _chain[i].absolutePose;
139  qWarning() << "AJT: jointIndex =" << _chain[i].jointIndex;
140  qWarning() << "AJT: dirty =" << _chain[i].dirty;
141  }
142  }
143 
144 protected:
145 
146  struct AnimChainElem {
147  AnimPose relativePose;
148  AnimPose absolutePose;
149  int jointIndex { -1 };
150  bool dirty { true };
151  };
152 
153  AnimChainElem _chain[N];
154  int _top { 0 };
155 };
156 
157 using AnimChain = AnimChainT<10>;
158 
159 #endif