Motive Animation System
An open source project by FPL.
 All Classes Functions Variables Typedefs Friends Pages
anim_table.h
1 // Copyright 2015 Google Inc. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef MOTIVE_ANIM_TABLE_H_
16 #define MOTIVE_ANIM_TABLE_H_
17 
18 #include <string>
19 #include <unordered_map>
20 #include <vector>
21 
22 #include "motive/anim.h"
23 
24 namespace motive {
25 
26 struct AnimTableFb;
27 struct AnimListFb;
28 struct AnimTableEmbeddedFb;
29 struct AnimListEmbeddedFb;
30 struct RigAnimFb;
31 class TableDescriberInterface;
32 
33 /// @class AnimTable
34 /// @brief Hold animation lists for several object types.
35 ///
36 /// A list of lists of animations.
37 ///
38 /// The outer list is indexed by `object`, the meaning of which is set by
39 /// the user, but is most likely an enum for the character being animated
40 /// (e.g. turtle, zombie, happy person, tall person, etc.).
41 ///
42 /// The inner list is indexed by `anim_idx`, the meaning of which is also set
43 /// by the user, but is most likely an enum for the action being animated
44 /// (e.g. idle, walk forward, jump, etc.).
45 ///
46 /// Duplicate animations are only loaded once. This allows different objects
47 /// to use the same animations without any memory overhead.
48 class AnimTable {
49  public:
50  // Array of animations corresponding to `anim_idx`.
51  // The meaning of `anim_idx` is set by the user, but is most likely an enum
52  // for the action being animated (e.g. idle, walk forward, jump, etc.).
53  typedef std::vector<std::string> ListFileNames;
54 
55  // Array of arrays of animations corresponding to `object`.
56  // The meaning of `object` is set by the user, but is most likely an enum
57  // for the character being animated (e.g. turtle, zombie, happy person,
58  // tall person, etc.).
59  typedef std::vector<ListFileNames> TableFileNames;
60 
61  /// Callback that loads `file_name` and returns a pointer to the raw data.
62  /// Optionally, the function can load the file into `scratch_buf`,
63  /// and then return `scratch_buf.c_str()`.
64  /// If the load fails, should return nullptr.
65  ///
66  /// Note: Motive does not make assumptions on file io, so the caller must
67  /// provide this function.
68  ///
69  typedef const char* LoadFn(const char* file_name, std::string* scratch_buf);
70 
71  ~AnimTable();
72 
73  /// Load the AnimTable specified in the FlatBuffer `params`.
74  /// For each animation in the AnimTable, `load_fn` is called to get the
75  /// to load the individual animation files, if they're not embedded in
76  /// table_fb. If they are embedded then `load_fn` can be nullptr.
77  /// `table_fb` can be discarded after this call.
78  bool InitFromFlatBuffers(const AnimTableFb& table_fb, LoadFn* load_fn);
79 
80  /// Load the animations specified in the FlatBuffer `list_fb`.
81  /// All of the loaded animations are for object 0.
82  bool InitFromFlatBuffers(const AnimListFb& list_fb, LoadFn* load_fn);
83 
84  /// Load the AnimTable specified in the vector of vectors.
85  /// The top level vector represents the `object` index.
86  /// The bottom level vector represents the `anim_idx`.
87  bool InitFromAnimFileNames(const TableFileNames& table_names,
88  LoadFn* load_fn);
89 
90  /// Load the AnimTable for only one `object`.
91  bool InitFromAnimFileNames(const ListFileNames& list_names, LoadFn* load_fn);
92 
93  /// Get an animation by index. This is fast and is the preferred way to
94  /// look up an animation.
95  /// @param object An enum defined by the caller specifying the object type.
96  /// For example, if you want separate animations lists for
97  /// cats and dogs, then object=0 could be cats, and object=1
98  /// could be dogs. The enum should run consecutively from
99  /// 0 to number of object types -1.
100  /// @param anim_idx An enum defined by the caller specifying the index into
101  /// the animation list for `object`. If your cat can run
102  /// and sleep, then you might make run=0 and sleep=1. Enum
103  /// should run consecutively from 0 to the number of
104  /// animations - 1. No need for the number of animations to
105  /// match between objects.
106  const RigAnim* Query(int object, int anim_idx) const {
107  const AnimIndex idx = CalculateIndex(object, anim_idx);
108  return idx == kInvalidAnimIndex ? nullptr : anims_[idx];
109  }
110 
111  /// Get an animation by name. This is slow and should be avoided when
112  /// possible.
113  const RigAnim* QueryByName(const char* anim_name) const {
114  return const_cast<AnimTable*>(this)->QueryByName(anim_name);
115  }
116 
117  /// Return animation that defines the complete rig of this object.
118  const RigAnim& DefiningAnim(int object) const {
119  return defining_anims_[object];
120  }
121 
122  /// Return size of the top-most vector. Recall that AnimTable is a vector
123  /// of vectors.
124  int NumObjects() const { return static_cast<int>(indices_.size()); }
125 
126  /// Return size of the bottom-most vector. Recall that AnimTable is a vector
127  /// of vectors.
128  int NumAnims(int object) const {
129  return static_cast<int>(indices_[object].size());
130  }
131 
132  /// Return the number of animations for which we've allocated memory.
133  /// Internally, we avoid duplicating animations.
134  int NumUniqueAnims() const { return static_cast<int>(anims_.size()); }
135 
136  private:
137  typedef uint16_t AnimIndex;
138  typedef std::vector<AnimIndex> AnimList;
139  typedef std::pair<std::string, AnimIndex> NameToIndex;
140  static const AnimIndex kInvalidAnimIndex = static_cast<AnimIndex>(-1);
141 
142  bool Load(TableDescriberInterface* describer, LoadFn* load_fn);
143  void AnimNames(std::vector<const char*>* anim_names) const;
144  size_t MaxAnimIndex() const;
145  size_t GatherObjectAnims(int object, const RigAnim** anims) const;
146  void CalculateDefiningAnims();
147 
148  RigAnim* QueryByName(const char* anim_name) {
149  auto map_entry = name_map_.find(anim_name);
150  if (map_entry == name_map_.end()) return nullptr;
151  return anims_[map_entry->second];
152  }
153 
154  AnimIndex CalculateIndex(int object, int anim_idx) const {
155  assert(0 <= object && object < static_cast<int>(indices_.size()));
156  const AnimList& list = indices_[object];
157 
158  assert(0 <= anim_idx && anim_idx < static_cast<int>(list.size()));
159  return list[anim_idx];
160  }
161 
162  /// Vector of vectors. Top vector is indexed by `object`. Bottom vector is
163  /// indexed by `anim_idx`. Holds an index into the `anims_` array.
164  std::vector<AnimList> indices_;
165 
166  /// For each `object` type, holds the index to the animation that defines
167  /// the complete rig. Animations may animate only a sub-rig, but we need to
168  /// have a complete rig for initialization.
169  std::vector<RigAnim> defining_anims_;
170 
171  /// Map animation name to an animation index.
172  /// Used for by-name lookups, and to avoid duplicate copies of the same
173  /// animation.
174  std::unordered_map<std::string, AnimIndex> name_map_;
175 
176  /// Animation data. Contains no duplicate entries, thanks to name_map_.
177  std::vector<RigAnim*> anims_;
178 };
179 
180 } // namespace motive
181 
182 #endif // MOTIVE_ANIM_TABLE_H_
const RigAnim * QueryByName(const char *anim_name) const
Definition: anim_table.h:113
const RigAnim & DefiningAnim(int object) const
Return animation that defines the complete rig of this object.
Definition: anim_table.h:118
Animation for a RigMotivator. Drives a fully rigged model.
Definition: anim.h:72
const char * LoadFn(const char *file_name, std::string *scratch_buf)
Definition: anim_table.h:69
const RigAnim * Query(int object, int anim_idx) const
Definition: anim_table.h:106
int NumObjects() const
Definition: anim_table.h:124
bool InitFromAnimFileNames(const TableFileNames &table_names, LoadFn *load_fn)
int NumAnims(int object) const
Definition: anim_table.h:128
bool InitFromFlatBuffers(const AnimTableFb &table_fb, LoadFn *load_fn)
Hold animation lists for several object types.
Definition: anim_table.h:48
int NumUniqueAnims() const
Definition: anim_table.h:134