gdk-graphics  1b6d84e044c2c953fd7c9501e628a67e80f4da0d
animated_model.h
1 // © Joseph Cameron - All Rights Reserved
2 
3 #ifndef GDK_GFX_ANIMATED_MODEL_H
4 #define GDK_GFX_ANIMATED_MODEL_H
5 
6 #include <memory>
7 #include <set>
8 #include <string>
9 #include <unordered_map>
10 #include <unordered_set>
11 
12 #include <gdk/vertex_data.h>
13 #include <gdk/graphics_types.h>
14 
15 namespace gdk
16 {
17  //WARN: work in progress, not usable
18  //TODO: write a basic skeleton animator.
19  //TODO: offer different strategies:
20  // Interpolation Strat
21  // Entirely interpolated: always interpolate everything. most cpu expensive, best results.
22  // Framerate locked: precalculate animations, user provides a "framerate", then interpolate
23  // up front, write to a map, use the map. Anims will have a frame rate and will take up
24  // more space but animation interp will not have to be calculated.
25  // Could also LRU cache the animation mixes, would have to parameterize the cache size,
26  // this would mean frequently used animation mixes also wouldnt be interpolated
27  // should also be able to manage many models, so multiple instances can take advantage of the lru and map,
28  // so these things wont grow linearly with instance count
29  // Vertex Transform strat
30  // cpu: done in a loop in c++: no special shaders needed therefore no implementation dependencies.
31  // could TRY to make use of worker threads, but would have to introduce params around work size etc.
32  // to get best results on whatever platform.
33  // gpu: final skeleton is uploaded to the gpu, transformations are performed in the vertex shader
34  // offloads work to the gpu but requires special vertex shader.
35  // gpu2: could try to offload interpolation step to gpu? Probably dont have enough instructions to do this
36  // in opengles2.
37  // gpu3: when/ifever I decide to work on vulkan, all this interp work is a great candidate for a compute shader
38  // user provides list of anims to blend and positions in ther timelines:
39  // upload the keyframe pairs for all anims to blend -> interpolation_compute -> vertex_shader -> frag
41  {
43  struct skeleton
44  {
45  struct bone
46  {
47  std::string name;
48 
49  graphics_mat4x4_type transform;
50 
51  std::unordered_set<bone *> children;
52  };
53 
55  std::unordered_set<std::unique_ptr<bone>> all_bones = {};
56 
58  std::unordered_set<bone *> root_bones = {};
59 
61  bool is_format_same(const skeleton &other) const
62  {
63  if (all_bones.size() != other.all_bones.size())
64  return false;
65 
66  auto iThisBone = all_bones.begin();
67  auto iThatBone = other.all_bones.begin();
68 
69  while (iThisBone != all_bones.end())
70  {
71  if ((*iThisBone)->name != (*iThatBone)->name)
72  return false;
73 
74  iThisBone++;
75  iThatBone++;
76  }
77 
78  // TODO: recurse root bones to make sure the trees
79  // have the same structure
80 
81  return true;
82  }
83  };
84 
87  class animation
88  {
89  public:
90  using key_frame_collection_type =
91  std::set<std::pair<float/*amount of time*/, skeleton>>;
92 
93  key_frame_collection_type m_KeyFrames;
94 
95  skeleton calculate_skeleton_at(float timeSec)
96  {
97  auto iLowFrame(m_KeyFrames.begin()),
98  iHighFrame(m_KeyFrames.begin());
99 
100  float interpolationWeight(0);
101 
102  for (auto i = m_KeyFrames.begin(); i != m_KeyFrames.end(); ++i)
103  {
104  if (timeSec < (*i).first)
105  {
106  iHighFrame = i;
107 
108  auto lowTime = iLowFrame->first;
109  auto highTime = iHighFrame->first;
110 
111  interpolationWeight =
112  (timeSec - lowTime) / (highTime - lowTime);
113 
114  break;
115  }
116 
117  iLowFrame = i;
118  }
119 
120  skeleton interpolated_skeleton;
121 
122  //TODO: interpolate the keyframes
123  //decompose translation, rotation, scale
124  //interpolate each component write
125  //to the interpolated_skeleton
126 
127  return interpolated_skeleton;
128  }
129 
130  animation(key_frame_collection_type &&aKeyFrames)
131  : m_KeyFrames(std::move(aKeyFrames))
132  {
133  const auto &firstSkeleton = m_KeyFrames.begin()->second;
134 
135  for (auto iFrame = m_KeyFrames.begin();
136  iFrame != m_KeyFrames.end(); ++iFrame)
137  if (!firstSkeleton.is_format_same(iFrame->second))
138  throw std::invalid_argument("animation: "
139  "skeleton format must be the same in all keyframes");
140  }
141  };
142 
144  std::unordered_map<std::string, animation> m_animations;
145 
147  vertex_data m_Buffer = vertex_data({});
148 
150  std::shared_ptr<gdk::model> m_pModel;
151 
152  void animate(const std::unordered_set<std::pair<std::string, float>>
153  &aContributingFrames)
154  {
155  //TODO: get skelies from all the arged animations,
156  //interpolate them to a final skele
157  //iterate vertex data, apply the final skele's
158  //matricies to the data
159  }
160  void animate(const std::pair<std::string, float> &aFrame)
161  {
162  //TODO: get skeleton
163  //iterate vertex data, apply the final skele's
164  //matricies to the data
165  }
166  };
167 }
168 
169 #endif
170 
Definition: animated_model.h:40
used to construct a model. Vertex data represents a set of vertex data in system memory ...
Definition: vertex_data.h:44
Definition: camera.h:9
Definition: animated_model.h:45